1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-01-10 00:43:27 +02:00
ComfyFactorio/maps/pirates/surfaces/surfaces.lua
2021-10-13 09:21:53 +01:00

725 lines
26 KiB
Lua

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 Boats = require 'maps.pirates.structures.boats.boats'
local Lobby = require 'maps.pirates.surfaces.lobby'
local Dock = require 'maps.pirates.surfaces.dock'
local Hold = require 'maps.pirates.surfaces.hold'
local Cabin = require 'maps.pirates.surfaces.cabin'
local Sea = require 'maps.pirates.surfaces.sea.sea'
local Islands = require 'maps.pirates.surfaces.islands.islands'
local Crowsnest = require 'maps.pirates.surfaces.crowsnest'
local Quest = require 'maps.pirates.quest'
local Parrot = require 'maps.pirates.parrot'
local ShopMerchants = require 'maps.pirates.shop.merchants'
local SurfacesCommon = require 'maps.pirates.surfaces.common'
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)
o.dynamic_data.chunks_loaded = o.dynamic_data.chunks_loaded or {}
if o.type == enum.ISLAND then
o.init_boat_state = Boats.enum_state.APPROACHING
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)
local memory = Memory.get_crew_memory()
-- 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
destination.dynamic_data.rocketsilonevercharged = true
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
if subtype ~= Islands.enum.STANDARD and subtype ~= Islands.enum.STANDARD_VARIANT and subtype ~= Islands.enum.RADIOACTIVE and subtype ~= Islands.enum.RED_DESERT then
destination.dynamic_data.hidden_ore_remaining_abstract = Utils.deepcopy(destination.static_params.abstract_ore_amounts)
end
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 = {}
elseif destination.type == enum.DOCK then
end
end
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()
-- Event_functions.flamer_nerfs()
memory.floating_pollution = 0
if destination.type == enum.ISLAND then
destination.dynamic_data.rocketsiloenergyneeded = Balance.silo_energy_needed_MJ() * 1000000
destination.dynamic_data.rocketgoldreward = Balance.launch_gold_reward()
if destination.subtype == Islands.enum.RADIOACTIVE then
destination.dynamic_data.time_remaining = -1
else
destination.dynamic_data.time_remaining = Math.ceil(Balance.max_time_on_island())
end
if destination.subtype ~= Islands.enum.FIRST and destination.subtype ~= Islands.enum.RADIOACTIVE then
Quest.initialise_random_quest()
else
-- if _DEBUG then
-- Quest.initialise_random_quest()
-- end
end
game.forces[memory.enemy_force_name].reset_evolution()
local base_evo = Balance.base_evolution()
game.forces[memory.enemy_force_name].evolution_factor = base_evo
destination.dynamic_data.evolution_accrued_leagues = base_evo
destination.dynamic_data.evolution_accrued_time = 0
destination.dynamic_data.evolution_accrued_nests = 0
destination.dynamic_data.evolution_accrued_silo = 0
memory.scripted_biters = {}
memory.scripted_unit_groups = {}
memory.floating_pollution = 0
if destination.subtype == Islands.enum.RADIOACTIVE then
Islands[Islands.enum.RADIOACTIVE].spawn_structures()
end
if destination and destination.surface_name and game.surfaces[destination.surface_name] and game.surfaces[destination.surface_name].valid and (not (destination.dynamic_data and destination.dynamic_data.initial_spawner_count)) then
--Note: This gives the wrong answer on the first island. Because the terrain hasn't finished generating yet.
destination.dynamic_data.initial_spawner_count = Common.spawner_count(game.surfaces[destination.surface_name])
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
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
end
local name = destination.static_params.name and destination.static_params.name or 'NameNotFound'
local message = 'Approaching destination ' .. (memory.destinationsvisited_indices and #memory.destinationsvisited_indices or 0) .. ', ' .. name .. '.'
if not (#memory.destinationsvisited_indices and #memory.destinationsvisited_indices == 1) then --don't need to notify for the first island
Server.to_discord_embed_raw((destination.static_params.discord_emoji or CoreData.comfy_emojis.wut) .. '[' .. memory.name .. '] ' .. message)
end
if destination.static_params.name == 'Dock' then
message = message .. ' ' .. 'Extra trades are available in the shop.'
end
Common.notify_force(game.forces[memory.force_name], message)
if destination.type == enum.ISLAND then
local points_to_avoid = {}
if destination.subtype ~= Islands.enum.RADIOACTIVE then
local silo_position = Islands.spawn_silo_setup()
points_to_avoid[#points_to_avoid + 1] = {x = silo_position.x, y = silo_position.y, r = 22}
end
Islands.spawn_ores_on_shorehit(destination, points_to_avoid)
if memory.overworldx >= Balance.covered_first_appears_at or _DEBUG then
local covered = Islands.spawn_covered(destination, points_to_avoid)
points_to_avoid[#points_to_avoid + 1] = {x = covered.x, y = covered.y, r = 25}
end
Islands.spawn_treasure_maps(destination, points_to_avoid)
Islands.spawn_ghosts(destination, points_to_avoid)
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
if memory.overworldx == 0 then
Parrot.parrot_0()
elseif memory.overworldx == 40 then
Parrot.parrot_40()
elseif memory.overworldx == 80 then
Parrot.parrot_80()
end
if destination.subtype == Islands.enum.RADIOACTIVE then
-- 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
Parrot.parrot_radioactive_tip_2()
end
if memory.merchant_ships_unlocked or _DEBUG then
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
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 = {}, {}
terrain_fn{p = p2, noise_generator = noise_generator, static_params = destination.static_params, tiles = tiles3, entities = entities3, decoratives = {}, seed = destination.seed}
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
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
local count = Math.ceil(v^(1/2))
if k == 'crude-oil' then
orestoadd[k] = {count = count, sizing_each = Common.oil_abstract_to_real(v)/count}
else
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]
entities[#entities + 1] = {name = k, position = p, amount = v.sizing_each}
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
for xstep = 0,300,3 do
local x = leftboundary * 32 + 16 + xstep
local y = (topboundary*32 + bottomboundary*32)/2 + ystep
local tiles3 = {}
terrain_fn{p = {x = x, y = y}, noise_generator = noise_generator, static_params = destination.static_params, tiles = tiles3, entities = {}, decoratives = {}, seed = destination.seed}
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
-- -- 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
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
surface.min_brightness = destination.static_params.min_brightness or 0
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
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)
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]
Quest.try_resolve_quest()
destination.dynamic_data.quest_type = nil
destination.dynamic_data.quest_reward = nil
destination.dynamic_data.quest_progress = nil
destination.dynamic_data.quest_progressneeded = nil
destination.dynamic_data.quest_complete = nil
-- 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
if player.character and player.character.valid then player.character.die(game.forces[memory.force_name]) end
player.teleport(memory.spawnpoint, seasurface)
end
end
destination.dynamic_data = {}
memory.scripted_biters = nil
memory.scripted_unit_groups = nil
memory.floating_pollution = nil
if memory.enemy_force_name then
local ef = game.forces[memory.enemy_force_name]
if ef and ef.valid then
game.forces[memory.enemy_force_name].reset_evolution()
local base_evo = Balance.base_evolution()
game.forces[memory.enemy_force_name].evolution_factor = base_evo
end
end
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)]
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
if memory.boat and (memory.boat.state == Boats.enum_state.ATSEA_SAILING or memory.boat.state == Boats.enum_state.ATSEA_LOADING_MAP) then
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)
local memory = Memory.get_crew_memory()
local surface = Hold.get_hold_surface(nth)
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
if memory.boat and (memory.boat.state == Boats.enum_state.ATSEA_SAILING or memory.boat.state == Boats.enum_state.ATSEA_LOADING_MAP) then
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)
local memory = Memory.get_crew_memory()
local surface = Cabin.get_cabin_surface()
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
end
function Public.player_exit_cabin(player, relative_pos)
local memory = Memory.get_crew_memory()
local surface
if memory.boat and (memory.boat.state == Boats.enum_state.ATSEA_SAILING or memory.boat.state == Boats.enum_state.ATSEA_LOADING_MAP) then
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