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 Balance = require ' maps.pirates.balance '
local Math = require ' maps.pirates.math '
local Common = require ' maps.pirates.common '
2022-06-15 23:00:18 +02:00
local SurfacesCommon = require ' maps.pirates.surfaces.common '
2021-10-13 10:21:53 +02:00
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 Ai = require ' maps.pirates.ai '
2022-03-19 23:20:55 +02:00
-- local Structures = require 'maps.pirates.structures.structures'
2021-10-13 10:21:53 +02:00
local Boats = require ' maps.pirates.structures.boats.boats '
local Surfaces = require ' maps.pirates.surfaces.surfaces '
2022-03-19 23:20:55 +02:00
-- local Progression = require 'maps.pirates.progression'
2022-10-10 21:03:51 +02:00
local IslandEnum = require ' maps.pirates.surfaces.islands.island_enum '
2022-02-26 20:25:48 +02:00
local Roles = require ' maps.pirates.roles.roles '
2021-10-13 10:21:53 +02:00
local Gui = require ' maps.pirates.gui.gui '
2022-03-19 23:20:55 +02:00
-- local Sea = require 'maps.pirates.surfaces.sea.sea'
-- local Hold = require 'maps.pirates.surfaces.hold'
-- local Cabin = require 'maps.pirates.surfaces.cabin'
-- local Crowsnest = require 'maps.pirates.surfaces.crowsnest'
-- local Ores = require 'maps.pirates.ores'
-- local Parrot = require 'maps.pirates.parrot'
2021-10-13 10:21:53 +02:00
local Kraken = require ' maps.pirates.surfaces.sea.kraken '
2022-03-10 23:09:06 +02:00
local Jailed = require ' utils.datastore.jail_data '
2021-10-13 10:21:53 +02:00
local Crew = require ' maps.pirates.crew '
local Quest = require ' maps.pirates.quest '
local Shop = require ' maps.pirates.shop.shop '
local Loot = require ' maps.pirates.loot '
local Task = require ' utils.task '
local Token = require ' utils.token '
local Classes = require ' maps.pirates.roles.classes '
2022-10-02 23:37:54 +02:00
local Ores = require ' maps.pirates.ores '
2021-10-13 10:21:53 +02:00
2022-05-29 13:36:27 +02:00
local Server = require ' utils.server '
2021-10-13 10:21:53 +02:00
-- local Modifers = require 'player_modifiers'
2022-03-19 23:20:55 +02:00
local tick_tack_trap = require ' maps.pirates.locally_maintained_comfy_forks.tick_tack_trap ' --'enemy' force, but that's okay
2022-03-04 19:57:58 +02:00
2021-10-13 10:21:53 +02:00
local Public = { }
2022-05-05 10:55:48 +02:00
function Public . silo_die ( )
2021-10-13 10:21:53 +02:00
local memory = Memory.get_crew_memory ( )
local destination = Common.current_destination ( )
2022-03-04 19:57:58 +02:00
local force = memory.force
2021-10-13 10:21:53 +02:00
if memory.game_lost == true then return end
destination.dynamic_data . rocketsilohp = 0
2022-02-24 21:39:03 +02:00
if destination.dynamic_data . rocketsilos and destination.dynamic_data . rocketsilos [ 1 ] and destination.dynamic_data . rocketsilos [ 1 ] . valid then
local surface = destination.dynamic_data . rocketsilos [ 1 ] . surface
2022-02-25 02:01:28 +02:00
surface.create_entity ( { name = ' big-artillery-explosion ' , position = destination.dynamic_data . rocketsilos [ 1 ] . position } )
2021-10-13 10:21:53 +02:00
if memory.boat and memory.boat . surface_name and surface.name == memory.boat . surface_name then
2022-03-19 23:20:55 +02:00
2022-03-04 19:57:58 +02:00
if CoreData.rocket_silo_death_causes_loss then
-- Crew.lose_life()
2022-05-29 13:36:27 +02:00
Crew.try_lose ( { ' pirates.loss_silo_destroyed ' } )
2022-03-05 02:11:11 +02:00
elseif ( not destination.dynamic_data . rocketlaunched ) then
2023-01-29 15:02:06 +02:00
if destination.static_params and destination.static_params . base_cost_to_undock and destination.static_params . base_cost_to_undock [ ' launch_rocket ' ] == true then
2023-01-12 18:58:53 +02:00
Crew.try_lose ( { ' pirates.loss_silo_destroyed_before_necessary_launch ' } )
else
Common.notify_force ( force , { ' pirates.silo_destroyed ' } )
end
2022-03-04 19:57:58 +02:00
end
2021-10-13 10:21:53 +02:00
end
2022-05-05 10:55:48 +02:00
destination.dynamic_data . rocketsilos [ 1 ] . die ( )
2022-02-24 21:39:03 +02:00
destination.dynamic_data . rocketsilos = nil
2021-10-13 10:21:53 +02:00
end
end
2022-05-05 10:55:48 +02:00
-- function Public.damage_silo(final_damage_amount)
-- if final_damage_amount == 0 then return end
-- local destination = Common.current_destination()
-- -- local memory = Memory.get_crew_memory()
2021-10-13 10:21:53 +02:00
2022-05-05 10:55:48 +02:00
-- -- if we are doing the 'no damage' quest, then damage in the first 20 seconds after landing doesn't count:
-- if destination and destination.dynamic_data and destination.dynamic_data.quest_type == Quest.enum.NODAMAGE then
-- if not (destination.dynamic_data.timer and destination.dynamic_data.timeratlandingtime and destination.dynamic_data.timer > destination.dynamic_data.timeratlandingtime + 20) then return end
-- end
2021-10-13 10:21:53 +02:00
2022-05-05 10:55:48 +02:00
-- -- manual 'resistance:'
-- local final_damage_amount2 = final_damage_amount / 4
2022-03-19 23:20:55 +02:00
2022-05-05 10:55:48 +02:00
-- destination.dynamic_data.rocketsilohp = Math.max(0, Math.floor(destination.dynamic_data.rocketsilohp - final_damage_amount2))
-- if destination.dynamic_data.rocketsilohp > destination.dynamic_data.rocketsilomaxhp then destination.dynamic_data.rocketsilohp = destination.dynamic_data.rocketsilomaxhp end
2021-10-13 10:21:53 +02:00
2022-05-05 10:55:48 +02:00
-- if destination.dynamic_data.rocketsilohp <= 0 then
-- -- if destination.dynamic_data.rocketsilohp <= 0 and (not destination.dynamic_data.rocketlaunched) then
-- Public.silo_die()
-- rendering.destroy(destination.dynamic_data.rocketsilohptext)
-- else
-- rendering.set_text(destination.dynamic_data.rocketsilohptext, 'HP: ' .. destination.dynamic_data.rocketsilohp .. ' / ' .. destination.dynamic_data.rocketsilomaxhp)
-- end
-- -- if destination.dynamic_data.rocketsilohp < destination.dynamic_data.rocketsilomaxhp / 2 and final_damage_amount > 0 then
-- -- Upgrades.trigger_poison()
-- -- end
-- end
2021-10-13 10:21:53 +02:00
2022-02-24 21:39:03 +02:00
local function biters_chew_stuff_faster ( event )
2022-06-15 23:00:18 +02:00
local memory = Memory.get_crew_memory ( )
2022-03-04 19:57:58 +02:00
local destination = Common.current_destination ( )
2021-10-13 10:21:53 +02:00
2022-02-24 21:39:03 +02:00
if not ( event.cause and event.cause . valid and event.cause . force and event.cause . force.name and event.entity and event.entity . valid and event.entity . force and event.entity . force.name ) then return end
2022-06-15 23:00:18 +02:00
if event.cause . force.name ~= memory.enemy_force_name then return end --Enemy Forces only
2021-10-13 10:21:53 +02:00
2022-02-24 21:39:03 +02:00
if ( event.entity . force.index == 3 or event.entity . force.name == ' environment ' ) then
event.entity . health = event.entity . health - event.final_damage_amount * 5
2023-01-12 18:58:53 +02:00
if destination and destination.type == Surfaces.enum . ISLAND and destination.subtype == IslandEnum.enum . MAZE then
2022-03-04 19:57:58 +02:00
event.entity . health = event.entity . health - event.final_damage_amount * 10
end
2022-02-27 18:42:25 +02:00
elseif event.entity . name == ' pipe ' then
event.entity . health = event.entity . health - event.final_damage_amount * 0.5
2022-02-24 21:39:03 +02:00
elseif event.entity . name == ' stone-furnace ' then
2022-02-27 18:42:25 +02:00
event.entity . health = event.entity . health - event.final_damage_amount * 0.5
2022-02-24 21:39:03 +02:00
elseif event.entity . name == ' wooden-chest ' or event.entity . name == ' stone-chest ' or event.entity . name == ' steel-chest ' then
2022-02-27 18:42:25 +02:00
event.entity . health = event.entity . health - event.final_damage_amount * 0.5
2022-02-24 21:39:03 +02:00
end
2021-10-13 10:21:53 +02:00
end
2022-05-05 10:55:48 +02:00
-- local function event_on_player_repaired_entity(event)
-- local entity = event.entity
-- if entity and entity.valid and entity.name and entity.name == 'artillery-turret' then
-- entity.health = entity.health - 2 --prevents repairing
-- end
-- --@TODO: somehow fix the fact that drones can repair the turret
-- end
local function protect_special_entities ( event )
2022-05-07 22:56:16 +02:00
-- local memory = Memory.get_crew_memory()
2021-10-13 10:21:53 +02:00
local entity = event.entity
2022-05-05 10:55:48 +02:00
if event.cause and event.cause . valid and entity and entity.valid then
local surfacedata = Surfaces.SurfacesCommon . decode_surface_name ( entity.surface . name )
2022-05-07 22:56:16 +02:00
-- local dest = Common.current_destination()
2022-05-05 10:55:48 +02:00
if surfacedata.type == Surfaces.enum . CROWSNEST or surfacedata.type == Surfaces.enum . LOBBY then
entity.health = entity.health + event.final_damage_amount
end
2021-10-13 10:21:53 +02:00
end
end
2022-05-06 02:47:27 +02:00
local function damage_to_silo ( event )
2021-10-13 10:21:53 +02:00
local memory = Memory.get_crew_memory ( )
2022-05-05 10:55:48 +02:00
local entity = event.entity
2021-10-13 10:21:53 +02:00
2022-05-05 10:55:48 +02:00
if event.cause and event.cause . valid and entity and entity.valid and entity.force . name == memory.force_name then
local destination = Common.current_destination ( )
2022-07-28 12:28:38 +02:00
if destination.dynamic_data . rocketsilos and
destination.dynamic_data . rocketsilos [ 1 ] and
destination.dynamic_data . rocketsilos [ 1 ] . valid and
entity == Common.current_destination ( ) . dynamic_data.rocketsilos [ 1 ]
then
2023-02-01 16:24:42 +02:00
if string.sub ( event.cause . force.name , 1 , 4 ) ~= ' crew ' then -- @Piratux: wonder why this is needed
2022-06-08 15:26:49 +02:00
-- play alert sound for all crew members
if memory.seconds_until_alert_sound_can_be_played_again <= 0 then
memory.seconds_until_alert_sound_can_be_played_again = Balance.alert_sound_max_frequency_in_seconds
for _ , player_index in pairs ( memory.crewplayerindices ) do
local player = game.players [ player_index ]
player.play_sound ( { path = ' utility/alert_destroyed ' , volume_modifier = 1 } )
end
end
2023-02-01 16:24:42 +02:00
local damage = event.original_damage_amount / Balance.silo_resistance_factor * ( 1 + Balance.biter_timeofday_bonus_damage ( event.cause . surface.darkness ) )
local remaining_health = Common.entity_damage_healthbar ( entity , damage , destination.dynamic_data )
if remaining_health and remaining_health <= 0 then
2022-05-05 10:55:48 +02:00
Public.silo_die ( )
else
2023-02-01 16:24:42 +02:00
destination.dynamic_data . rocketsilohp = remaining_health
2021-10-13 10:21:53 +02:00
end
2022-05-05 10:55:48 +02:00
else
entity.health = entity.prototype . max_health
2021-10-13 10:21:53 +02:00
end
end
end
end
2022-03-15 20:50:19 +02:00
local function damage_to_enemyboat_spawners ( event )
2021-10-13 10:21:53 +02:00
local memory = Memory.get_crew_memory ( )
2023-02-01 16:24:42 +02:00
local destination = Common.current_destination ( )
2021-10-13 10:21:53 +02:00
2023-02-01 16:24:42 +02:00
if destination.dynamic_data . enemyboats and
# destination.dynamic_data . enemyboats > 0 and
2022-07-28 12:28:38 +02:00
event.cause and
event.cause . valid and
event.entity and
event.entity . valid and
event.entity . force.name == memory.enemy_force_name
then
2023-02-01 16:24:42 +02:00
for i = 1 , # destination.dynamic_data . enemyboats do
local eb = destination.dynamic_data . enemyboats [ i ]
2022-07-28 12:28:38 +02:00
if eb.spawner and eb.spawner . valid and event.entity == eb.spawner then
-- if eb.spawner and eb.spawner.valid and event.entity == eb.spawner and eb.state == Structures.Boats.enum_state.APPROACHING then
local damage = event.final_damage_amount
2023-02-01 16:24:42 +02:00
local remaining_health = Common.entity_damage_healthbar ( event.entity , damage , destination.dynamic_data )
2022-07-28 12:28:38 +02:00
2023-02-01 16:24:42 +02:00
if remaining_health and remaining_health <= 0 then
event.entity . die ( )
end
end
end
end
end
2022-07-28 12:28:38 +02:00
2023-02-01 16:24:42 +02:00
-- Does not include krakens or biter boat spawners
local function damage_to_elite_spawners ( event )
local memory = Memory.get_crew_memory ( )
local destination = Common.current_destination ( )
2022-07-28 12:28:38 +02:00
2023-02-01 16:24:42 +02:00
if destination.dynamic_data . elite_spawners and
# destination.dynamic_data . elite_spawners > 0 and
event.cause and
event.cause . valid and
event.entity and
event.entity . valid and
event.entity . force.name == memory.enemy_force_name
then
for i = 1 , # destination.dynamic_data . elite_spawners do
local spawner = destination.dynamic_data . elite_spawners [ i ]
if spawner and spawner.valid and event.entity == spawner then
local damage = event.final_damage_amount
local remaining_health = Common.entity_damage_healthbar ( event.entity , damage , destination.dynamic_data )
if remaining_health and remaining_health <= 0 then
2022-07-28 12:28:38 +02:00
event.entity . die ( )
2021-10-13 10:21:53 +02:00
end
end
end
end
end
2023-02-04 17:14:48 +02:00
local function damage_to_elite_biters ( event )
local memory = Memory.get_crew_memory ( )
local elite_biters = memory.elite_biters
if elite_biters and
event.cause and
event.cause . valid and
event.entity and
event.entity . valid and
event.entity . force.name == memory.enemy_force_name
then
if elite_biters [ event.entity . unit_number ] then
local damage = event.final_damage_amount
local remaining_health = Common.entity_damage_healthbar ( event.entity , damage )
if remaining_health and remaining_health <= 0 then
memory.elite_biters [ event.entity . unit_number ] = nil
event.entity . die ( )
end
end
end
end
2022-03-14 14:44:30 +02:00
local function damage_to_artillery ( event )
2022-06-08 15:26:49 +02:00
local memory = Memory.get_crew_memory ( )
2021-10-13 10:21:53 +02:00
if not event.cause then return end
if not event.cause . valid then return end
if not event.cause . name then return end
2023-02-01 16:24:42 +02:00
if Utils.contains ( CoreData.enemy_units , event.cause . name ) then
2022-06-15 23:00:18 +02:00
if event.cause . force.name ~= memory.enemy_force_name then return end
2022-05-05 10:55:48 +02:00
2022-06-08 15:26:49 +02:00
-- play alert sound for all crew members
if memory.seconds_until_alert_sound_can_be_played_again <= 0 then
memory.seconds_until_alert_sound_can_be_played_again = Balance.alert_sound_max_frequency_in_seconds
for _ , player_index in pairs ( memory.crewplayerindices ) do
local player = game.players [ player_index ]
player.play_sound ( { path = ' utility/alert_destroyed ' , volume_modifier = 1 } )
end
end
2022-06-08 15:44:24 +02:00
2021-10-13 10:21:53 +02:00
-- remove resistances:
2022-05-05 10:55:48 +02:00
-- event.entity.health = event.entity.health + event.final_damage_amount - event.original_damage_amount
2023-02-01 16:24:42 +02:00
local damage = event.original_damage_amount / Balance.cannon_resistance_factor
damage = damage * ( 1 + Balance.biter_timeofday_bonus_damage ( event.cause . surface.darkness ) )
local remaining_health = Common.entity_damage_healthbar ( event.entity , damage , memory.boat )
if remaining_health and remaining_health <= 0 then
2022-05-05 10:55:48 +02:00
event.entity . die ( )
end
2021-10-13 10:21:53 +02:00
else
2022-05-05 10:55:48 +02:00
event.entity . health = event.entity . prototype.max_health --nothing else should damage it
2021-10-13 10:21:53 +02:00
end
end
2022-03-14 14:44:30 +02:00
local function damage_to_krakens ( event )
2021-10-13 10:21:53 +02:00
2022-06-15 23:00:18 +02:00
if not event.entity then return end
if not event.entity . valid then return end
if not event.entity . name then return end
if event.entity . name ~= ' biter-spawner ' then return end
2022-03-14 14:44:30 +02:00
2021-10-13 10:21:53 +02:00
if not event.cause then return end
if not event.cause . valid then return end
if not event.cause . name then return end
2022-03-14 14:44:30 +02:00
local memory = Memory.get_crew_memory ( )
2022-06-15 23:00:18 +02:00
if event.entity . force.name ~= memory.enemy_force_name then return end
2021-10-13 10:21:53 +02:00
local surface_name = memory.boat and memory.boat . surface_name
if not ( surface_name == memory.sea_name ) then return end
local unit_number = event.entity . unit_number
local damage = event.final_damage_amount
local adjusted_damage = damage
2022-03-14 23:38:44 +02:00
if event.damage_type . name and event.damage_type . name == ' poison ' then
adjusted_damage = adjusted_damage / 1.25
elseif event.damage_type . name and ( event.damage_type . name == ' explosion ' ) then
adjusted_damage = adjusted_damage / 1.5
2022-03-13 20:19:59 +02:00
elseif event.damage_type . name and ( event.damage_type . name == ' fire ' ) then
2022-03-14 23:38:44 +02:00
adjusted_damage = adjusted_damage / 1.25
2021-10-13 10:21:53 +02:00
end
-- and additionally:
if event.cause . name == ' artillery-turret ' then
2022-07-30 15:02:24 +02:00
adjusted_damage = adjusted_damage / 1.5
2021-10-13 10:21:53 +02:00
end
2022-03-03 02:19:20 +02:00
if event.damage_type . name and ( event.damage_type . name == ' laser ' ) then
2022-06-04 17:35:51 +02:00
adjusted_damage = adjusted_damage / 7 --laser turrets are in range. give some resistance
2022-03-03 02:19:20 +02:00
end
2023-02-01 16:24:42 +02:00
-- There should be a better way to do it than this...
if memory.healthbars and memory.healthbars [ unit_number ] then
local kraken_id = memory.healthbars [ unit_number ] . id
local remaining_health = Common.entity_damage_healthbar ( event.entity , adjusted_damage )
if remaining_health and remaining_health <= 0 then
Kraken.kraken_die ( kraken_id )
end
2021-10-13 10:21:53 +02:00
end
end
2022-03-14 14:44:30 +02:00
local function damage_to_players_changes ( event )
2021-10-13 10:21:53 +02:00
local memory = Memory.get_crew_memory ( )
if not event.cause then return end
if not event.cause . valid then return end
if not event.cause . name then return end
2021-10-14 11:23:34 +02:00
-- if not (event.cause.name == 'small-biter') or (event.cause.name == 'small-spitter') or (event.cause.name == 'medium-biter') or (event.cause.name == 'medium-spitter') or (event.cause.name == 'big-biter') or (event.cause.name == 'big-spitter') or (event.cause.name == 'behemoth-biter') or (event.cause.name == 'behemoth-spitter') then return end
2021-10-13 10:21:53 +02:00
local player_index = event.entity . player.index
2022-07-17 22:12:27 +02:00
local player = game.players [ player_index ]
2022-07-28 19:15:31 +02:00
if not player then return end
if not player.valid then return end
if not player.character then return end
if not player.character . valid then return end
2022-03-04 19:57:58 +02:00
2022-07-28 19:15:31 +02:00
local class = Classes.get_class ( player_index )
2022-03-14 14:44:30 +02:00
local damage_multiplier = 1
2021-10-13 10:21:53 +02:00
2022-06-02 15:07:17 +02:00
--game.print('on damage info: {name: ' .. event.damage_type.name .. ', object_name: ' .. event.damage_type.object_name .. '}')
2022-06-04 16:17:41 +02:00
if event.damage_type . name == ' poison ' then --make all poison damage stronger against players
2022-06-02 21:08:55 +02:00
damage_multiplier = damage_multiplier * Balance.poison_damage_multiplier
2022-03-17 03:40:18 +02:00
else
2022-07-17 22:12:27 +02:00
if class then
if class == Classes.enum . SCOUT then
damage_multiplier = damage_multiplier * Balance.scout_damage_taken_multiplier
2022-07-28 12:28:38 +02:00
-- merchant is disabled
2022-07-17 22:12:27 +02:00
-- elseif class == Classes.enum.MERCHANT then
-- damage_multiplier = damage_multiplier * 1.10
elseif class == Classes.enum . SAMURAI then
damage_multiplier = damage_multiplier * Balance.samurai_damage_taken_multiplier
elseif class == Classes.enum . HATAMOTO then
damage_multiplier = damage_multiplier * Balance.hatamoto_damage_taken_multiplier
2022-07-31 11:23:59 +02:00
elseif class == Classes.enum . ROCK_EATER then
damage_multiplier = damage_multiplier * Balance.rock_eater_damage_taken_multiplier
2022-07-17 22:12:27 +02:00
elseif class == Classes.enum . IRON_LEG then
if memory.class_auxiliary_data [ player_index ] and memory.class_auxiliary_data [ player_index ] . iron_leg_active then
damage_multiplier = damage_multiplier * Balance.iron_leg_damage_taken_multiplier
end
elseif class == Classes.enum . VETERAN then
local chance = Balance.veteran_on_hit_slow_chance
2023-02-01 16:24:42 +02:00
if Math.random ( ) <= chance then
2022-07-17 22:12:27 +02:00
-- only certain targets accept stickers
2023-02-01 16:24:42 +02:00
if Utils.contains ( CoreData.enemy_units , event.cause . name ) then
2022-07-17 22:12:27 +02:00
player.surface . create_entity {
name = ' slowdown-sticker ' ,
position = player.character . position ,
speed = 1.5 ,
force = player.force ,
target = event.cause
}
end
end
-- else
-- damage_multiplier = damage_multiplier * (1 + Balance.bonus_damage_to_humans())
2022-03-17 03:40:18 +02:00
end
end
2022-03-14 14:44:30 +02:00
end
2021-10-13 10:21:53 +02:00
2022-06-15 23:00:18 +02:00
if event.cause . force.name == memory.enemy_force_name then
2022-05-06 02:47:27 +02:00
damage_multiplier = damage_multiplier * ( 1 + Balance.biter_timeofday_bonus_damage ( event.cause . surface.darkness ) )
end --Enemy Forces
2022-07-16 20:46:23 +02:00
-- game.print('name: ' .. event.cause.name .. ' damage: ' .. event.final_damage_amount)
-- game.print('multiplier: ' .. damage_multiplier)
2021-10-13 10:21:53 +02:00
2022-03-14 14:44:30 +02:00
if damage_multiplier > 1 then
event.entity . health = event.entity . health - event.final_damage_amount * ( damage_multiplier - 1 )
2022-06-04 15:43:08 +02:00
elseif damage_multiplier < 1 and event.final_health > 0 then --lethal damage case isn't this easy
2022-03-14 14:44:30 +02:00
event.entity . health = event.entity . health + event.final_damage_amount * ( 1 - damage_multiplier )
2021-10-13 10:21:53 +02:00
end
2022-06-02 15:07:17 +02:00
-- deal with damage reduction on lethal damage for players
2022-06-04 15:43:08 +02:00
-- Piratux wrote this code — it tracks player health (except passive regen), and intervenes on a lethal damage event, so it should work most of the time.
2022-06-02 15:07:17 +02:00
local global_memory = Memory.get_global_memory ( )
if damage_multiplier < 1 and event.final_health <= 0 then
local damage_dealt = event.final_damage_amount * damage_multiplier
if damage_dealt < global_memory.last_players_health [ player_index ] then
event.entity . health = global_memory.last_players_health [ player_index ] - damage_dealt
end
end
global_memory.last_players_health [ player_index ] = event.entity . health
2021-10-13 10:21:53 +02:00
end
2022-05-06 02:47:27 +02:00
local function other_enemy_damage_bonuses ( event )
if not event.cause then return end
if not event.cause . valid then return end
if not event.cause . name then return end
if not event.cause . surface then return end
if not event.cause . surface.valid then return end
if event.damage_type . name == ' impact ' then return end --avoid circularity
2022-06-15 23:00:18 +02:00
local memory = Memory.get_crew_memory ( )
2022-05-06 02:47:27 +02:00
-- if not (event.cause.name == 'small-biter') or (event.cause.name == 'small-spitter') or (event.cause.name == 'medium-biter') or (event.cause.name == 'medium-spitter') or (event.cause.name == 'big-biter') or (event.cause.name == 'big-spitter') or (event.cause.name == 'behemoth-biter') or (event.cause.name == 'behemoth-spitter') then return end
2022-06-15 23:00:18 +02:00
if event.cause . force.name ~= memory.enemy_force_name then return end --Enemy Forces
2022-05-06 02:47:27 +02:00
local bonusDamage = event.final_damage_amount * Balance.biter_timeofday_bonus_damage ( event.cause . surface.darkness )
if bonusDamage > 0 then
event.entity . damage ( bonusDamage , event.cause . force , ' impact ' , event.cause )
end
end
2023-02-08 19:41:52 +02:00
-- @TODO: Fix elite biters getting one shotted by Samurai/Hatamoto classes (it doesn't play well with virtual health) as well as check for other inconsistencies/issues when damaging entities with virtual health
2022-03-14 14:44:30 +02:00
local function damage_dealt_by_players_changes ( event )
2021-10-13 10:21:53 +02:00
local memory = Memory.get_crew_memory ( )
2022-03-14 14:44:30 +02:00
if not event.cause then return end
if not event.cause . valid then return end
if not event.entity . valid then return end
if event.cause . name ~= ' character ' then return end
2023-02-03 23:24:11 +02:00
if event.entity . name == ' character ' then return end
2022-03-14 14:44:30 +02:00
2021-10-13 10:21:53 +02:00
local character = event.cause
local player = character.player
2022-03-14 14:44:30 +02:00
local physical = event.damage_type . name == ' physical '
local acid = event.damage_type . name == ' acid '
2021-10-13 10:21:53 +02:00
local player_index = player.index
2022-07-28 19:15:31 +02:00
local class = Classes.get_class ( player_index )
2021-10-13 10:21:53 +02:00
2023-02-03 23:24:11 +02:00
-- Lethal damage must be unaffected, otherwise enemy will never die.
-- @Future reference: when implementing damage changes for mobs with healthbar, make this check with healthbar health too
if event.final_health > 0 then
if class and class == Classes.enum . SCOUT then
event.entity . health = event.entity . health + ( 1 - Balance.scout_damage_dealt_multiplier ) * event.final_damage_amount
elseif class and ( class == Classes.enum . SAMURAI or class == Classes.enum . HATAMOTO ) then
local samurai = class == Classes.enum . SAMURAI
local hatamoto = class == Classes.enum . HATAMOTO
2022-03-07 11:50:25 +02:00
2023-02-03 23:24:11 +02:00
local no_weapon = ( not ( character.get_inventory ( defines.inventory . character_guns ) and character.get_inventory ( defines.inventory . character_guns ) [ character.selected_gun_index ] and character.get_inventory ( defines.inventory . character_guns ) [ character.selected_gun_index ] . valid_for_read ) )
2022-03-07 11:50:25 +02:00
2023-02-03 23:24:11 +02:00
local melee = ( physical or acid ) and no_weapon
2022-03-07 11:50:25 +02:00
2023-02-03 23:24:11 +02:00
local extra_damage_to_deal = 0
2022-03-07 11:50:25 +02:00
2023-02-03 23:24:11 +02:00
local big_number = 1000
2022-03-07 11:50:25 +02:00
2023-02-03 23:24:11 +02:00
local extra_physical_damage_from_research_multiplier = 1 + memory.force . get_ammo_damage_modifier ( ' bullet ' )
2022-03-07 11:50:25 +02:00
2023-02-03 23:24:11 +02:00
if melee then
if physical then
if samurai then
extra_damage_to_deal = Balance.samurai_damage_dealt_with_melee * extra_physical_damage_from_research_multiplier
elseif hatamoto then
extra_damage_to_deal = Balance.hatamoto_damage_dealt_with_melee * extra_physical_damage_from_research_multiplier
end
elseif acid then --this hacky stuff is to implement repeated spillover splash damage, whilst getting around the fact that if ovekill damage takes something to zero health, we can't tell in that event how much double-overkill damage should be dealt by reading off its HP. This code assumes that characters only deal acid damage via this function.
extra_damage_to_deal = event.original_damage_amount * big_number
end
else
2022-03-07 11:50:25 +02:00
if samurai then
2023-02-03 23:24:11 +02:00
event.entity . health = event.entity . health + ( 1 - Balance.samurai_damage_dealt_when_not_melee_multiplier ) * event.final_damage_amount
2022-03-07 11:50:25 +02:00
elseif hatamoto then
2023-02-03 23:24:11 +02:00
event.entity . health = event.entity . health + ( 1 - Balance.hatamoto_damage_dealt_when_not_melee_multiplier ) * event.final_damage_amount
2022-03-07 11:50:25 +02:00
end
end
2022-03-04 19:57:58 +02:00
2023-02-03 23:24:11 +02:00
if extra_damage_to_deal > 0 then
if event.entity . health >= extra_damage_to_deal then
event.entity . damage ( extra_damage_to_deal , character.force , ' impact ' , character ) --using .damage rather than subtracting from health directly plays better with entities which use healthbars
else
local surplus = ( extra_damage_to_deal - event.entity . health ) * 0.8
event.entity . die ( character.force , character )
local nearest = player.surface . find_nearest_enemy { position = player.position , max_distance = 2 , force = player.force }
if nearest and nearest.valid then
nearest.damage ( surplus / big_number , character.force , ' acid ' , character )
end
2022-03-07 11:50:25 +02:00
end
end
2022-03-04 19:57:58 +02:00
end
2023-02-03 23:24:11 +02:00
if physical then
2022-03-04 19:57:58 +02:00
2023-02-03 23:24:11 +02:00
-- QUARTERMASTER BUFFS
local nearby_players = player.surface . find_entities_filtered { position = player.position , radius = Balance.quartermaster_range , type = { ' character ' } }
2022-03-19 23:20:55 +02:00
2023-02-03 23:24:11 +02:00
for _ , p2 in pairs ( nearby_players ) do
if p2.player and p2.player . valid then
local p2_index = p2.player . index
if event.entity . valid and player_index ~= p2_index and Classes.get_class ( p2_index ) == Classes.enum . QUARTERMASTER then
event.entity . damage ( ( Balance.quartermaster_bonus_physical_damage - 1 ) * event.final_damage_amount , character.force , ' impact ' , character ) --triggers this function again, but not physical this time
end
2022-03-07 11:50:25 +02:00
end
2022-03-04 19:57:58 +02:00
end
2022-03-14 14:44:30 +02:00
2023-02-03 23:24:11 +02:00
-- PISTOL BUFFS
if character.shooting_state . state ~= defines.shooting . not_shooting then
local weapon = character.get_inventory ( defines.inventory . character_guns ) [ character.selected_gun_index ]
local ammo = character.get_inventory ( defines.inventory . character_ammo ) [ character.selected_gun_index ]
if event.entity . valid and weapon.valid_for_read and ammo.valid_for_read and weapon.name == ' pistol ' and ( ammo.name == ' firearm-magazine ' or ammo.name == ' piercing-rounds-magazine ' or ammo.name == ' uranium-rounds-magazine ' ) then
event.entity . damage ( event.final_damage_amount * ( Balance.pistol_damage_multiplier ( ) - 1 ) , character.force , ' impact ' , character ) --triggers this function again, but not physical this time
end
2022-03-14 14:44:30 +02:00
end
end
2021-10-13 10:21:53 +02:00
end
end
2022-03-14 14:44:30 +02:00
2022-03-04 20:24:04 +02:00
local function swamp_resist_poison ( event )
2022-06-15 23:00:18 +02:00
local memory = Memory.get_crew_memory ( )
2021-10-13 10:21:53 +02:00
local entity = event.entity
if not entity.valid then return end
if not ( event.damage_type . name and event.damage_type . name == ' poison ' ) then return end
local destination = Common.current_destination ( )
2023-01-12 18:58:53 +02:00
if not ( destination and destination.subtype == IslandEnum.enum . SWAMP ) then return end
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
if not ( destination.surface_name == entity.surface . name ) then return end
2022-06-15 23:00:18 +02:00
if not ( ( entity.type and entity.type == ' tree ' ) or ( event.entity . force and event.entity . force.name == memory.enemy_force_name ) ) then return end
2021-10-13 10:21:53 +02:00
local damage = event.final_damage_amount
event.entity . health = event.entity . health + damage
end
2022-03-04 20:24:04 +02:00
local function maze_walls_resistance ( event )
2022-03-19 23:20:55 +02:00
-- local memory = Memory.get_crew_memory()
2022-03-04 20:24:04 +02:00
local entity = event.entity
if not entity.valid then return end
local destination = Common.current_destination ( )
2023-01-12 18:58:53 +02:00
if not ( destination and destination.subtype == IslandEnum.enum . MAZE ) then return end
2022-03-19 23:20:55 +02:00
2022-03-04 20:24:04 +02:00
if not ( destination.surface_name == entity.surface . name ) then return end
if not ( ( entity.type and entity.type == ' tree ' ) or entity.name == ' rock-huge ' or entity.name == ' rock-big ' or entity.name == ' sand-rock-big ' ) then return end
local damage = event.final_damage_amount
2022-03-05 21:56:41 +02:00
if ( event.damage_type . name and ( event.damage_type . name == ' explosion ' or event.damage_type . name == ' poison ' ) ) then
event.entity . health = event.entity . health + damage
2022-03-13 20:19:59 +02:00
elseif event.damage_type . name and event.damage_type . name == ' fire ' then
-- put out forest fires:
for _ , e2 in pairs ( entity.surface . find_entities_filtered ( { area = { { entity.position . x - 4 , entity.position . y - 4 } , { entity.position . x + 4 , entity.position . y + 4 } } , name = " fire-flame-on-tree " } ) ) do
if e2.valid then e2.destroy ( ) end
end
2022-03-05 21:56:41 +02:00
else
2022-03-13 20:19:59 +02:00
if string.sub ( event.cause . force.name , 1 , 4 ) == ' crew ' then --player damage only
event.entity . health = event.entity . health + damage * 0.9
end
2022-03-05 21:56:41 +02:00
end
2022-03-04 20:24:04 +02:00
end
2022-03-28 01:40:32 +02:00
2022-05-06 02:47:27 +02:00
-- functions like this need to be rewritten so they play nicely with healthbars:
-- local function damage_to_enemies(event)
-- local memory = Memory.get_crew_memory()
2022-03-28 01:40:32 +02:00
2022-05-06 02:47:27 +02:00
-- if not (event.entity and event.entity.valid and event.entity.force and event.entity.force.valid) then return end
2022-03-28 01:40:32 +02:00
2022-06-15 23:00:18 +02:00
-- if event.entity.force.name ~= memory.enemy_force_name then return end
2022-05-06 02:47:27 +02:00
-- local evo = memory.evolution_factor
2022-03-28 01:40:32 +02:00
2022-05-06 02:47:27 +02:00
-- if evo and evo > 1 and event.final_health > 0 then --lethal damage needs to be unaffected, else they never die
2022-03-28 01:40:32 +02:00
2022-05-06 02:47:27 +02:00
-- local surplus = evo - 1
2022-03-28 01:40:32 +02:00
2022-05-06 02:47:27 +02:00
-- local damage_multiplier = 1/(1 + Common.surplus_evo_biter_health_fractional_modifier(surplus))
2022-03-28 01:40:32 +02:00
2022-05-06 02:47:27 +02:00
-- if damage_multiplier < 1 then
-- event.entity.health = event.entity.health + event.final_damage_amount * (1 - damage_multiplier)
-- end
-- end
2022-03-28 01:40:32 +02:00
2022-05-06 02:47:27 +02:00
-- -- commented out as this is done elsewhere:
-- -- if event.damage_type.name == 'poison' then
-- -- event.entity.health = event.entity.health + event.final_damage_amount
-- -- end
-- end
2022-03-28 01:40:32 +02:00
2021-10-13 10:21:53 +02:00
local function event_on_entity_damaged ( event )
local crew_id = nil
2022-06-15 23:00:18 +02:00
if not crew_id and event.entity . surface.valid then crew_id = SurfacesCommon.decode_surface_name ( event.entity . surface.name ) . crewid end
if not crew_id and event.force . valid then crew_id = Common.get_id_from_force_name ( event.force . name ) end
if not crew_id and event.entity . valid then crew_id = Common.get_id_from_force_name ( event.entity . force.name ) end
2021-10-13 10:21:53 +02:00
Memory.set_working_id ( crew_id )
2022-03-19 23:20:55 +02:00
-- local memory = Memory.get_crew_memory()
-- local difficulty = memory.difficulty
2021-10-13 10:21:53 +02:00
if not event.entity . valid then return end
2022-05-06 02:47:27 +02:00
damage_to_silo ( event )
damage_to_krakens ( event )
damage_to_enemyboat_spawners ( event )
2023-02-01 16:24:42 +02:00
damage_to_elite_spawners ( event )
2023-02-04 17:14:48 +02:00
damage_to_elite_biters ( event )
2022-05-06 02:47:27 +02:00
if event.entity and event.entity . valid and event.entity . name and event.entity . name == ' artillery-turret ' then
damage_to_artillery ( event )
end
2022-05-05 10:55:48 +02:00
protect_special_entities ( event )
2022-05-06 02:47:27 +02:00
if not event.entity . valid then return end -- need to call again, healthbar'd object might have been killed by script, so we shouldn't proceed now
2021-10-13 10:21:53 +02:00
if not event.entity . health then return end
2022-03-19 23:20:55 +02:00
2022-05-06 02:47:27 +02:00
if ( event.entity and event.entity . valid and event.entity . name and event.entity . name == ' character ' ) then
damage_to_players_changes ( event )
else
other_enemy_damage_bonuses ( event )
end
2022-03-19 23:20:55 +02:00
2022-02-24 21:39:03 +02:00
biters_chew_stuff_faster ( event )
2022-03-04 20:24:04 +02:00
swamp_resist_poison ( event )
maze_walls_resistance ( event )
2022-03-14 14:44:30 +02:00
damage_dealt_by_players_changes ( event )
2021-10-13 10:21:53 +02:00
2022-05-06 02:47:27 +02:00
-- damage_to_enemies(event)
2021-10-13 10:21:53 +02:00
end
2022-03-04 19:57:58 +02:00
function Public . load_some_map_chunks ( destination_index , fraction , force_load ) --in a 'spear' from the left
2022-03-19 23:20:55 +02:00
--WARNING: if force_load is true, THIS DOES NOT PLAY NICELY WITH DELAYED TASKS. log(_inspect{global_memory.working_id}) was observed to vary before and after this function.
2021-10-13 10:21:53 +02:00
force_load = force_load or false
local memory = Memory.get_crew_memory ( )
local destination_data = memory.destinations [ destination_index ]
if not destination_data then return end
local surface_name = destination_data.surface_name
if not surface_name then return end
local surface = game.surfaces [ surface_name ]
if not surface then return end
local w , h = surface.map_gen_settings . width , surface.map_gen_settings . height
local c = { x = 0 , y = 0 }
if destination_data.static_params and destination_data.static_params . islandcenter_position then
c = destination_data.static_params . islandcenter_position
w = w - 2 * Math.abs ( c.x )
h = h - 2 * Math.abs ( c.y )
end
local l = Math.max ( Math.floor ( w / 32 ) , Math.floor ( h / 32 ) )
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
local i , j , s = 0 , 0 , { x = 0 , y = 0 }
while i < 4 * l ^ 2 and j <= fraction * w / 32 * h / 32 do
i = i + 1
if s.y < 0 then
s.y = - s.y
elseif s.y > 0 then
s = { x = s.x + 1 , y = 1 - s.y }
else
s = { x = 0 , y = - ( s.x + 1 ) }
end
if s.x <= w / 32 and s.y <= h / 32 / 2 and s.y >= - h / 32 / 2 then
surface.request_to_generate_chunks ( { x = c.x - w / 2 + 32 * s.x , y = c.y + 32 * s.y } , 0.1 )
j = j + 1
end
end
if force_load then
2022-03-19 23:20:55 +02:00
surface.force_generate_chunk_requests ( ) --WARNING: THIS DOES NOT PLAY NICELY WITH DELAYED TASKS. log(_inspect{global_memory.working_id}) was observed to vary before and after this function.
2021-10-13 10:21:53 +02:00
end
end
2022-10-02 23:37:54 +02:00
function Public . load_some_map_chunks_random_order ( surface , destination_data , fraction ) -- The reason we might want to do this is because of algorithms like the labyrinth code, which make directionally biased patterns if you don't generate chunks in a random order
2022-03-04 19:57:58 +02:00
if not surface then return end
2022-10-02 23:37:54 +02:00
if not destination_data then return end
2022-03-04 19:57:58 +02:00
local shuffled_chunks
if not destination_data.dynamic_data then destination_data.dynamic_data = { } end
if not destination_data.dynamic_data . shuffled_chunks then
local w , h = surface.map_gen_settings . width , surface.map_gen_settings . height
local c = { x = 0 , y = 0 }
if destination_data.static_params and destination_data.static_params . islandcenter_position then
c = destination_data.static_params . islandcenter_position
w = w - 2 * Math.abs ( c.x )
h = h - 2 * Math.abs ( c.y )
end
2022-03-19 23:20:55 +02:00
2022-03-04 19:57:58 +02:00
local chunks_list = { }
for i = 0 , Math.ceil ( w / 32 - 1 ) , 1 do
for j = 0 , Math.ceil ( h / 32 - 1 ) , 1 do
table.insert ( chunks_list , { x = c.x - w / 2 + 32 * i , y = c.y - h / 2 + 32 * j } )
end
end
2022-03-19 23:20:55 +02:00
2022-03-04 19:57:58 +02:00
destination_data.dynamic_data . shuffled_chunks = Math.shuffle ( chunks_list )
end
shuffled_chunks = destination_data.dynamic_data . shuffled_chunks
for i = 1 , # shuffled_chunks do
if i > fraction * # shuffled_chunks then
break
end
surface.request_to_generate_chunks ( shuffled_chunks [ i ] , 0.2 )
end
end
2022-06-02 15:49:18 +02:00
-- local function event_pre_player_mined_item(event)
-- -- figure out which crew this is about:
-- -- local crew_id = nil
2022-06-15 23:00:18 +02:00
-- -- if event.player_index and game.players[event.player_index].valid then crew_id = Common.get_id_from_force_name(game.players[event.player_index].force.name) end
2022-06-02 15:49:18 +02:00
-- -- Memory.set_working_id(crew_id)
-- -- local memory = Memory.get_crew_memory()
2022-03-19 23:20:55 +02:00
2022-06-02 15:49:18 +02:00
-- -- if memory.planet[1].type.id == 11 then --rocky planet
-- -- if event.entity.name == 'rock-huge' or event.entity.name == 'rock-big' or event.entity.name == 'sand-rock-big' then
-- -- Event_functions.trap(event.entity, false)
-- -- event.entity.destroy()
-- -- Event_functions.rocky_loot(event)
-- -- end
-- -- end
-- end
2021-10-13 10:21:53 +02:00
2023-02-06 22:58:54 +02:00
local function player_mined_tree ( event )
2021-10-13 10:21:53 +02:00
local memory = Memory.get_crew_memory ( )
local destination = Common.current_destination ( )
2023-02-06 22:58:54 +02:00
local player = game.players [ event.player_index ]
local entity = event.entity
2022-10-11 19:52:23 +02:00
local class = Classes.get_class ( event.player_index )
2023-02-06 22:58:54 +02:00
local available = destination.dynamic_data . wood_remaining
local starting = destination.static_params . starting_wood
2022-03-19 23:20:55 +02:00
2023-02-06 22:58:54 +02:00
if not ( available and destination.type == Surfaces.enum . ISLAND ) then return end
2021-10-13 10:21:53 +02:00
2023-02-06 22:58:54 +02:00
if destination.subtype == IslandEnum.enum . MAZE then
if Math.random ( 1 , 38 ) == 1 then
tick_tack_trap ( memory.enemy_force_name , entity.surface , entity.position )
return
end
end
2022-03-14 14:44:30 +02:00
2023-02-06 22:58:54 +02:00
local give = { }
2022-03-14 14:44:30 +02:00
2023-02-19 18:57:38 +02:00
local baseamount = 5
2023-02-06 22:58:54 +02:00
--minimum 1 wood
local amount = Math.clamp ( 1 , Math.max ( 1 , Math.ceil ( available ) ) , Math.ceil ( baseamount * Balance.island_richness_avg_multiplier ( ) * available / starting ) )
2023-01-30 17:19:45 +02:00
2023-02-06 22:58:54 +02:00
destination.dynamic_data . wood_remaining = destination.dynamic_data . wood_remaining - amount
2023-01-30 17:19:45 +02:00
2023-02-06 22:58:54 +02:00
give [ # give + 1 ] = { name = ' wood ' , count = amount }
2023-02-01 22:17:22 +02:00
2023-02-06 22:58:54 +02:00
if class == Classes.enum . LUMBERJACK then
Classes.lumberjack_bonus_items ( give )
else
if Math.random ( Balance.every_nth_tree_gives_coins ) == 1 then --tuned
local a = 5
give [ # give + 1 ] = { name = ' coin ' , count = a }
memory.playtesting_stats . coins_gained_by_trees_and_rocks = memory.playtesting_stats . coins_gained_by_trees_and_rocks + a
end
end
2022-03-19 23:20:55 +02:00
2023-02-06 22:58:54 +02:00
Common.give ( player , give , entity.position )
2022-06-01 21:45:13 +02:00
2023-02-06 22:58:54 +02:00
if destination.subtype ~= IslandEnum.enum . FIRST then
2023-02-12 00:01:53 +02:00
if Math.random ( 512 ) == 1 then
2023-02-06 22:58:54 +02:00
local placed = Ores.try_ore_spawn ( entity.surface , entity.position , entity.name , 0 , true )
if placed then
Common.notify_player_expected ( player , { ' pirates.ore_discovered ' } )
end
2023-02-12 00:01:53 +02:00
elseif Math.random ( 1024 ) == 1 then
2023-02-06 22:58:54 +02:00
local e = entity.surface . create_entity { name = ' wooden-chest ' , position = entity.position , force = memory.ancient_friendly_force_name }
if e and e.valid then
e.minable = false
e.rotatable = false
e.destructible = false
local inv = e.get_inventory ( defines.inventory . chest )
local loot = Loot.wooden_chest_loot ( )
for i = 1 , # loot do
local l = loot [ i ]
inv.insert ( l )
2021-10-13 10:21:53 +02:00
end
2023-02-06 22:58:54 +02:00
Common.notify_player_expected ( player , { ' pirates.chest_discovered ' } )
2021-10-13 10:21:53 +02:00
end
end
2023-02-06 22:58:54 +02:00
end
end
2022-03-19 23:20:55 +02:00
2023-02-06 22:58:54 +02:00
local function player_mined_fish ( event )
local memory = Memory.get_crew_memory ( )
local destination = Common.current_destination ( )
local player = game.players [ event.player_index ]
local entity = event.entity
local class = Classes.get_class ( event.player_index )
2021-10-13 10:21:53 +02:00
2023-02-06 22:58:54 +02:00
-- Prevent dull strategy being staying in sea for long time catching as many fish as possible (as there is kind of infinite amount there)
-- NOTE: This however doesn't prevent catching fish with inserters, but that shouldn't matter much?
local boat_is_at_sea = Boats.is_boat_at_sea ( )
local fish_caught_while_at_sea = - 1
if boat_is_at_sea and memory.boat and memory.boat . fish_caught_while_at_sea then
fish_caught_while_at_sea = memory.boat . fish_caught_while_at_sea
end
2022-11-18 15:49:03 +02:00
2023-02-06 22:58:54 +02:00
if ( not boat_is_at_sea ) or ( boat_is_at_sea and fish_caught_while_at_sea < Balance.maximum_fish_allowed_to_catch_at_sea ) then
if fish_caught_while_at_sea ~= - 1 then
memory.boat . fish_caught_while_at_sea = memory.boat . fish_caught_while_at_sea + 1
end
2022-10-02 23:37:54 +02:00
2023-02-06 22:58:54 +02:00
local fish_amount = Balance.base_caught_fish_amount
local to_give = { }
2022-10-02 23:37:54 +02:00
2023-02-06 22:58:54 +02:00
if class == Classes.enum . FISHERMAN then
fish_amount = fish_amount + Balance.fisherman_fish_bonus
to_give [ # to_give + 1 ] = { name = ' raw-fish ' , count = fish_amount }
2023-01-11 22:15:55 +02:00
2023-02-06 22:58:54 +02:00
elseif class == Classes.enum . MASTER_ANGLER then
fish_amount = fish_amount + Balance.master_angler_fish_bonus
to_give [ # to_give + 1 ] = { name = ' raw-fish ' , count = fish_amount }
to_give [ # to_give + 1 ] = { name = ' coin ' , count = Balance.master_angler_coin_bonus }
2022-10-02 23:37:54 +02:00
2023-02-06 22:58:54 +02:00
elseif class == Classes.enum . DREDGER then
fish_amount = fish_amount + Balance.dredger_fish_bonus
to_give [ # to_give + 1 ] = { name = ' raw-fish ' , count = fish_amount }
to_give [ # to_give + 1 ] = Loot.dredger_loot ( ) [ 1 ]
2023-01-11 22:15:55 +02:00
else
2023-02-06 22:58:54 +02:00
to_give [ # to_give + 1 ] = { name = ' raw-fish ' , count = fish_amount }
2022-03-04 19:57:58 +02:00
end
2022-03-19 23:20:55 +02:00
2023-02-06 22:58:54 +02:00
Common.give ( player , to_give , entity.position )
2022-03-19 23:20:55 +02:00
2023-02-06 22:58:54 +02:00
if destination and destination.dynamic_data and destination.dynamic_data . quest_type and ( not destination.dynamic_data . quest_complete ) then
if destination.dynamic_data . quest_type == Quest.enum . FISH then
destination.dynamic_data . quest_progress = destination.dynamic_data . quest_progress + fish_amount
Quest.try_resolve_quest ( )
end
2022-02-24 21:39:03 +02:00
end
2023-02-06 22:58:54 +02:00
else
Common.notify_player_error ( player , { ' pirates.cant_catch_fish ' } )
end
end
2022-02-24 21:39:03 +02:00
2023-02-06 22:58:54 +02:00
local function player_mined_resource ( event )
local memory = Memory.get_crew_memory ( )
-- local destination = Common.current_destination()
local player = game.players [ event.player_index ]
local entity = event.entity
-- local class = Classes.get_class(event.player_index)
local give = { }
-- prospector and chief excavator are disabled
-- if memory.overworldx > 0 then --no coins on first map, else the optimal strategy is to handmine everything there
-- if memory.classes_table and memory.classes_table[event.player_index] and memory.classes_table[event.player_index] == Classes.enum.PROSPECTOR then
-- local a = 3
-- give[#give + 1] = {name = 'coin', count = a}
-- memory.playtesting_stats.coins_gained_by_ore = memory.playtesting_stats.coins_gained_by_ore + a
-- give[#give + 1] = {name = entity.name, count = 6}
-- elseif memory.classes_table and memory.classes_table[event.player_index] and memory.classes_table[event.player_index] == Classes.enum.CHIEF_EXCAVATOR then
-- local a = 4
-- give[#give + 1] = {name = 'coin', count = a}
-- memory.playtesting_stats.coins_gained_by_ore = memory.playtesting_stats.coins_gained_by_ore + a
-- give[#give + 1] = {name = entity.name, count = 12}
-- else
-- if memory.overworldx > 0 then
-- local a = 1
-- give[#give + 1] = {name = 'coin', count = a}
-- memory.playtesting_stats.coins_gained_by_ore = memory.playtesting_stats.coins_gained_by_ore + a
-- end
-- give[#give + 1] = {name = entity.name, count = 2}
-- end
-- else
-- give[#give + 1] = {name = entity.name, count = 2}
-- end
if memory.overworldx > 0 then --no coins on first map, else the optimal strategy is to handmine everything there
local a = 1
give [ # give + 1 ] = { name = ' coin ' , count = a }
memory.playtesting_stats . coins_gained_by_ore = memory.playtesting_stats . coins_gained_by_ore + a
end
2022-07-28 12:28:38 +02:00
2023-02-06 22:58:54 +02:00
give [ # give + 1 ] = { name = entity.name , count = 2 }
2022-03-19 23:20:55 +02:00
2023-02-06 22:58:54 +02:00
Common.give ( player , give , entity.position )
end
2021-10-13 10:21:53 +02:00
2023-02-06 22:58:54 +02:00
local function player_mined_rock ( event )
local memory = Memory.get_crew_memory ( )
local destination = Common.current_destination ( )
local player = game.players [ event.player_index ]
local entity = event.entity
-- local class = Classes.get_class(event.player_index)
2021-10-13 10:21:53 +02:00
2023-02-19 15:47:35 +02:00
-- local available = destination.dynamic_data.rock_material_remaining
2023-02-06 22:58:54 +02:00
-- local starting = destination.static_params.starting_rock_material
2022-10-02 23:37:54 +02:00
2023-02-19 15:47:35 +02:00
-- if not (available and destination.type == Surfaces.enum.ISLAND) then return end
2021-10-13 10:21:53 +02:00
2023-02-06 22:58:54 +02:00
if destination.subtype == IslandEnum.enum . MAZE then
if Math.random ( 1 , 35 ) == 1 then
tick_tack_trap ( memory.enemy_force_name , entity.surface , entity.position )
end
end
2022-10-02 23:37:54 +02:00
2023-02-06 22:58:54 +02:00
if destination.subtype == IslandEnum.enum . CAVE then
Ores.try_give_ore ( player , entity.position , entity.name )
2022-10-02 23:37:54 +02:00
2023-02-06 22:58:54 +02:00
if Math.random ( 1 , 35 ) == 1 then
tick_tack_trap ( memory.enemy_force_name , entity.surface , entity.position )
2022-10-02 23:37:54 +02:00
2023-02-06 22:58:54 +02:00
elseif Math.random ( 1 , 20 ) == 1 then
entity.surface . create_entity ( { name = ' compilatron ' , position = entity.position , force = memory.force } )
if destination and destination.dynamic_data and destination.dynamic_data . quest_type and ( not destination.dynamic_data . quest_complete ) then
if destination.dynamic_data . quest_type == Quest.enum . COMPILATRON then
destination.dynamic_data . quest_progress = destination.dynamic_data . quest_progress + 1
Quest.try_resolve_quest ( )
2021-10-13 10:21:53 +02:00
end
2023-02-06 22:58:54 +02:00
end
2022-10-02 23:37:54 +02:00
2023-02-06 22:58:54 +02:00
elseif Math.random ( 1 , 10 ) == 1 then
if Math.random ( 1 , 4 ) == 1 then
entity.surface . create_entity { name = Common.get_random_worm_type ( memory.evolution_factor ) , position = entity.position , force = memory.enemy_force_name }
2022-03-04 19:57:58 +02:00
else
2023-02-06 22:58:54 +02:00
local biter = entity.surface . create_entity { name = Common.get_random_unit_type ( memory.evolution_factor ) , position = entity.position , force = memory.enemy_force_name }
Common.try_make_biter_elite ( biter )
end
end
else
local c = event.buffer . get_contents ( )
table.sort ( c , function ( a , b ) return a.name < b.name end )
local c2 = { }
if memory.overworldx >= 0 then --used to be only later levels
if entity.name == ' rock-huge ' then
local a = 55
c2 [ # c2 + 1 ] = { name = ' coin ' , count = a , color = CoreData.colors . coin }
memory.playtesting_stats . coins_gained_by_trees_and_rocks = memory.playtesting_stats . coins_gained_by_trees_and_rocks + a
if Math.random ( 1 , 35 ) == 1 then
c2 [ # c2 + 1 ] = { name = ' crude-oil-barrel ' , count = 1 , color = CoreData.colors . oil }
2021-10-13 10:21:53 +02:00
end
2023-02-06 22:58:54 +02:00
else
local a = 35
c2 [ # c2 + 1 ] = { name = ' coin ' , count = a , color = CoreData.colors . coin }
memory.playtesting_stats . coins_gained_by_trees_and_rocks = memory.playtesting_stats . coins_gained_by_trees_and_rocks + a
if Math.random ( 1 , 35 * 3 ) == 1 then
c2 [ # c2 + 1 ] = { name = ' crude-oil-barrel ' , count = 1 , color = CoreData.colors . oil }
end
end
end
for k , v in pairs ( c ) do
if k == ' coal ' and # c2 <= 1 then --if oil, then no coal
c2 [ # c2 + 1 ] = { name = k , count = Math.ceil ( v * Balance.island_richness_avg_multiplier ( ) ) , color = CoreData.colors . coal }
elseif k == ' stone ' then
c2 [ # c2 + 1 ] = { name = k , count = Math.ceil ( v * Balance.island_richness_avg_multiplier ( ) ) , color = CoreData.colors . stone }
end
end
Common.give ( player , c2 , entity.position )
2023-02-19 15:47:35 +02:00
-- destination.dynamic_data.rock_material_remaining = available
2022-03-19 23:20:55 +02:00
2023-02-06 22:58:54 +02:00
if Surfaces.get_scope ( destination ) . break_rock then
destination.dynamic_data . ore_spawn_points_to_avoid = destination.dynamic_data . ore_spawn_points_to_avoid or { }
local points_to_avoid = destination.dynamic_data . ore_spawn_points_to_avoid
local can_place_ores = true
-- Sometimes there can be very little amount of rocks here, so it probably isn't bad idea to spawn ore on top of another
if destination.subtype ~= IslandEnum.enum . WALKWAYS then
for _ , pos in ipairs ( points_to_avoid ) do
if Math.distance ( pos , entity.position ) < Balance.min_ore_spawn_distance then
can_place_ores = false
break
2022-03-04 19:57:58 +02:00
end
end
2023-02-06 22:58:54 +02:00
end
2023-01-30 17:19:45 +02:00
2023-02-06 22:58:54 +02:00
if can_place_ores then
local placed = Surfaces.get_scope ( destination ) . break_rock ( entity.surface , entity.position , entity.name )
if placed then
points_to_avoid [ # points_to_avoid + 1 ] = { x = entity.position . x , y = entity.position . y }
2022-03-19 23:20:55 +02:00
end
2021-10-13 10:21:53 +02:00
end
end
2023-02-06 22:58:54 +02:00
end
end
local function event_on_player_mined_entity ( event )
if not event.buffer then return end
if not event.player_index then return end
local player = game.players [ event.player_index ]
if not player.valid then return end
local entity = event.entity
if not entity.valid then return end
local crew_id = Common.get_id_from_force_name ( player.force . name )
Memory.set_working_id ( crew_id )
2021-10-13 10:21:53 +02:00
2023-02-06 22:58:54 +02:00
if player.surface . name == ' gulag ' then
2021-10-13 10:21:53 +02:00
event.buffer . clear ( )
2023-02-06 22:58:54 +02:00
return
end
if entity.type == ' tree ' then
player_mined_tree ( event )
2023-02-08 23:37:23 +02:00
event.buffer . clear ( )
2023-02-06 22:58:54 +02:00
elseif entity.type == ' fish ' then
player_mined_fish ( event )
2023-02-08 23:37:23 +02:00
event.buffer . clear ( )
2023-02-06 22:58:54 +02:00
elseif entity.name == ' coal ' or entity.name == ' stone ' or entity.name == ' copper-ore ' or entity.name == ' iron-ore ' then
player_mined_resource ( event )
2023-02-08 23:37:23 +02:00
event.buffer . clear ( )
2023-02-06 22:58:54 +02:00
elseif entity.name == ' rock-huge ' or entity.name == ' rock-big ' or entity.name == ' sand-rock-big ' then
player_mined_rock ( event )
2023-02-08 23:37:23 +02:00
event.buffer . clear ( )
2021-10-13 10:21:53 +02:00
end
end
local function shred_nearby_simple_entities ( entity )
local memory = Memory.get_crew_memory ( )
2022-03-01 23:59:48 +02:00
if memory.evolution_factor < 0.25 then return end
2021-10-13 10:21:53 +02:00
local simple_entities = entity.surface . find_entities_filtered ( { type = { ' simple-entity ' , ' tree ' } , area = { { entity.position . x - 3 , entity.position . y - 3 } , { entity.position . x + 3 , entity.position . y + 3 } } } )
if # simple_entities == 0 then return end
for i = 1 , # simple_entities , 1 do
if not simple_entities [ i ] then break end
if simple_entities [ i ] . valid then
simple_entities [ i ] . die ( memory.enemy_force_name , simple_entities [ i ] )
end
end
end
local function base_kill_rewards ( event )
local memory = Memory.get_crew_memory ( )
2022-03-04 19:57:58 +02:00
local destination = Common.current_destination ( )
2021-10-13 10:21:53 +02:00
local entity = event.entity
if not ( entity and entity.valid ) then return end
if not ( event.force and event.force . valid ) then return end
2022-04-30 00:48:34 +02:00
local entity_name = entity.name
2021-10-13 10:21:53 +02:00
2023-01-31 00:25:43 +02:00
-- Don't give coins for friendly biter death
if Utils.contains ( CoreData.enemy_units , entity_name ) and entity.force and entity.force . name == memory.force_name then
return
end
2022-02-28 18:36:46 +02:00
local revenge_target
if event.cause and event.cause . valid and event.cause . name == ' character ' then
revenge_target = event.cause
end
2022-07-17 22:12:27 +02:00
-- This gives enemy loot straight to combat robot owner's inventory instead of dropping it on the ground
2022-07-23 21:26:54 +02:00
if event.cause and ( event.cause . name == ' defender ' or event.cause . name == ' distractor ' or event.cause . name == ' destroyer ' ) then
2022-07-17 22:12:27 +02:00
if event.cause . combat_robot_owner and event.cause . combat_robot_owner.valid then
revenge_target = event.cause . combat_robot_owner
end
end
2022-10-11 19:52:23 +02:00
local class_is_chef = false
2022-07-08 13:58:23 +02:00
if revenge_target and
revenge_target.valid and
revenge_target.player and
2022-10-11 19:52:23 +02:00
revenge_target.player . index
2022-07-08 13:58:23 +02:00
then
2022-10-11 19:52:23 +02:00
class_is_chef = Classes.get_class ( revenge_target.player . index ) == Classes.enum . CHEF
2022-07-08 13:58:23 +02:00
end
2022-04-30 00:48:34 +02:00
local iron_amount
local coin_amount
2022-07-08 13:58:23 +02:00
local fish_amount
2022-04-30 00:48:34 +02:00
if entity_name == ' small-worm-turret ' then
iron_amount = 5
2022-06-02 13:57:15 +02:00
coin_amount = 50
2022-07-31 11:23:59 +02:00
fish_amount = 1 * Balance.chef_fish_received_for_worm_kill
2022-05-06 14:00:57 +02:00
memory.playtesting_stats . coins_gained_by_nests_and_worms = memory.playtesting_stats . coins_gained_by_nests_and_worms + coin_amount
2022-04-30 00:48:34 +02:00
elseif entity_name == ' medium-worm-turret ' then
iron_amount = 20
2022-06-02 13:57:15 +02:00
coin_amount = 90
2022-07-31 11:23:59 +02:00
fish_amount = 2 * Balance.chef_fish_received_for_worm_kill
2022-05-06 14:00:57 +02:00
memory.playtesting_stats . coins_gained_by_nests_and_worms = memory.playtesting_stats . coins_gained_by_nests_and_worms + coin_amount
2022-04-30 00:48:34 +02:00
elseif entity_name == ' biter-spawner ' or entity_name == ' spitter-spawner ' then
iron_amount = 30
2022-05-06 14:00:57 +02:00
coin_amount = 100
2022-07-08 13:58:23 +02:00
fish_amount = 0 -- cooking spawners don't really fit class fantasy imo
2022-05-06 14:00:57 +02:00
memory.playtesting_stats . coins_gained_by_nests_and_worms = memory.playtesting_stats . coins_gained_by_nests_and_worms + coin_amount
2022-04-30 00:48:34 +02:00
elseif entity_name == ' big-worm-turret ' then
iron_amount = 30
2022-06-02 13:57:15 +02:00
coin_amount = 140
2022-07-31 11:23:59 +02:00
fish_amount = 2 * Balance.chef_fish_received_for_worm_kill
2022-05-06 14:00:57 +02:00
memory.playtesting_stats . coins_gained_by_nests_and_worms = memory.playtesting_stats . coins_gained_by_nests_and_worms + coin_amount
2022-04-30 00:48:34 +02:00
elseif entity_name == ' behemoth-worm-turret ' then
iron_amount = 50
2022-06-02 13:57:15 +02:00
coin_amount = 260
2022-07-31 11:23:59 +02:00
fish_amount = 3 * Balance.chef_fish_received_for_worm_kill
2022-05-07 22:56:16 +02:00
memory.playtesting_stats . coins_gained_by_nests_and_worms = memory.playtesting_stats . coins_gained_by_nests_and_worms + coin_amount
2022-05-06 14:43:59 +02:00
elseif memory.overworldx > 0 then --avoid coin farming on first island
if entity_name == ' small-biter ' then
-- if Math.random(2) == 1 then
-- coin_amount = 1
-- end
coin_amount = 1
2022-07-31 11:23:59 +02:00
fish_amount = 0 * Balance.chef_fish_received_for_biter_kill
2022-05-06 14:43:59 +02:00
memory.playtesting_stats . coins_gained_by_biters = memory.playtesting_stats . coins_gained_by_biters + coin_amount
elseif entity_name == ' small-spitter ' then
coin_amount = 1
2022-07-31 11:23:59 +02:00
fish_amount = 0 * Balance.chef_fish_received_for_biter_kill
2022-05-06 14:43:59 +02:00
memory.playtesting_stats . coins_gained_by_biters = memory.playtesting_stats . coins_gained_by_biters + coin_amount
elseif entity_name == ' medium-biter ' then
coin_amount = 2
2022-07-31 11:23:59 +02:00
fish_amount = 1 * Balance.chef_fish_received_for_biter_kill
2022-05-06 14:43:59 +02:00
memory.playtesting_stats . coins_gained_by_biters = memory.playtesting_stats . coins_gained_by_biters + coin_amount
elseif entity_name == ' medium-spitter ' then
coin_amount = 2
2022-07-31 11:23:59 +02:00
fish_amount = 1 * Balance.chef_fish_received_for_biter_kill
2022-05-06 14:43:59 +02:00
memory.playtesting_stats . coins_gained_by_biters = memory.playtesting_stats . coins_gained_by_biters + coin_amount
elseif entity_name == ' big-biter ' then
coin_amount = 4
2022-07-31 11:23:59 +02:00
fish_amount = 2 * Balance.chef_fish_received_for_biter_kill
2022-05-06 14:43:59 +02:00
memory.playtesting_stats . coins_gained_by_biters = memory.playtesting_stats . coins_gained_by_biters + coin_amount
elseif entity_name == ' big-spitter ' then
coin_amount = 4
2022-07-31 11:23:59 +02:00
fish_amount = 2 * Balance.chef_fish_received_for_biter_kill
2022-05-06 14:43:59 +02:00
memory.playtesting_stats . coins_gained_by_biters = memory.playtesting_stats . coins_gained_by_biters + coin_amount
elseif entity_name == ' behemoth-biter ' then
coin_amount = 8
2022-07-31 11:23:59 +02:00
fish_amount = 3 * Balance.chef_fish_received_for_biter_kill
2022-05-06 14:43:59 +02:00
memory.playtesting_stats . coins_gained_by_biters = memory.playtesting_stats . coins_gained_by_biters + coin_amount
elseif entity_name == ' behemoth-spitter ' then
coin_amount = 8
2022-07-31 11:23:59 +02:00
fish_amount = 3 * Balance.chef_fish_received_for_biter_kill
2022-05-06 14:43:59 +02:00
memory.playtesting_stats . coins_gained_by_biters = memory.playtesting_stats . coins_gained_by_biters + coin_amount
end
2021-10-13 10:21:53 +02:00
end
2022-07-08 13:58:23 +02:00
local stack = { }
2021-10-13 10:21:53 +02:00
2022-07-08 13:58:23 +02:00
if iron_amount and iron_amount > 0 then
stack [ # stack + 1 ] = { name = ' iron-plate ' , count = iron_amount }
end
if coin_amount and coin_amount > 0 then
stack [ # stack + 1 ] = { name = ' coin ' , count = coin_amount }
end
2022-07-31 11:23:59 +02:00
if class_is_chef and fish_amount and fish_amount > 0 then
2022-07-08 13:58:23 +02:00
stack [ # stack + 1 ] = { name = ' raw-fish ' , count = fish_amount }
end
2022-05-29 13:36:27 +02:00
2022-07-08 13:58:23 +02:00
local short_form = ( not iron_amount ) and true or false
2022-10-30 23:25:30 +02:00
-- revenge_target.player can be nil if player kills itself
if revenge_target and revenge_target.player then
2022-07-08 13:58:23 +02:00
Common.give ( revenge_target.player , stack , revenge_target.player . position , short_form , entity.surface , entity.position )
else
if event.cause and event.cause . valid and event.cause . position then
Common.give ( nil , stack , event.cause . position , short_form , entity.surface , entity.position )
2021-10-13 10:21:53 +02:00
else
2022-07-08 13:58:23 +02:00
Common.give ( nil , stack , entity.position , short_form , entity.surface )
2021-10-13 10:21:53 +02:00
end
2022-02-28 18:36:46 +02:00
end
2022-03-19 23:20:55 +02:00
2022-04-30 00:48:34 +02:00
if ( entity_name == ' biter-spawner ' or entity_name == ' spitter-spawner ' ) and entity.position and entity.surface and entity.surface . valid then
2022-02-28 18:36:46 +02:00
--check if its a boat biter entity
local boat_spawner = false
2023-02-01 16:24:42 +02:00
if destination.dynamic_data . enemyboats then
for i = 1 , # destination.dynamic_data . enemyboats do
local eb = destination.dynamic_data . enemyboats [ i ]
2022-02-28 18:36:46 +02:00
if eb.spawner and eb.spawner . valid and event.entity == eb.spawner then
boat_spawner = true
break
end
2021-10-13 10:21:53 +02:00
end
end
2022-02-28 18:36:46 +02:00
if boat_spawner then
Ai.revenge_group ( entity.surface , entity.position , revenge_target , ' biter ' , 0.3 , 2 )
2022-04-30 00:48:34 +02:00
elseif entity_name == ' biter-spawner ' then
2022-02-28 18:36:46 +02:00
Ai.revenge_group ( entity.surface , entity.position , revenge_target , ' biter ' )
else
Ai.revenge_group ( entity.surface , entity.position , revenge_target , ' spitter ' )
end
2021-10-13 10:21:53 +02:00
end
end
local function spawner_died ( event )
2023-02-06 22:58:54 +02:00
-- local memory = Memory.get_crew_memory()
2021-10-13 10:21:53 +02:00
local destination = Common.current_destination ( )
2022-03-11 18:46:02 +02:00
if ( destination and destination.type and destination.type == Surfaces.enum . ISLAND ) then
2022-03-17 03:40:18 +02:00
local not_boat = true
2023-02-01 16:24:42 +02:00
if destination.dynamic_data . enemyboats and # destination.dynamic_data . enemyboats > 0 then
for i = 1 , # destination.dynamic_data . enemyboats do
local eb = destination.dynamic_data . enemyboats [ i ]
2022-03-17 03:40:18 +02:00
if eb.spawner and eb.spawner . valid and event.entity and event.entity . valid and event.entity == eb.spawner then
not_boat = false
break
end
end
end
if not_boat then
local extra_evo = Balance.evolution_per_nest_kill ( )
Common.increment_evo ( extra_evo )
2022-03-19 23:20:55 +02:00
2022-03-17 03:40:18 +02:00
if destination.dynamic_data then
destination.dynamic_data . evolution_accrued_nests = destination.dynamic_data . evolution_accrued_nests + extra_evo
end
2022-03-11 18:46:02 +02:00
end
2022-03-07 11:50:25 +02:00
end
2021-10-13 10:21:53 +02:00
end
local function event_on_entity_died ( event )
2022-03-17 03:40:18 +02:00
--== MODDING NOTE: event.cause is not always provided.
2021-10-13 10:21:53 +02:00
local entity = event.entity
if not ( entity and entity.valid ) then return end
if not ( event.force and event.force . valid ) then return end
2022-06-15 23:00:18 +02:00
local crew_id = Common.get_id_from_force_name ( entity.force . name )
2021-10-13 10:21:53 +02:00
Memory.set_working_id ( crew_id )
local memory = Memory.get_crew_memory ( )
2022-07-07 22:01:45 +02:00
if not Common.is_id_valid ( memory.id ) then return end
2021-10-13 10:21:53 +02:00
base_kill_rewards ( event )
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
if memory.scripted_biters and entity.type == ' unit ' and entity.force . name == memory.enemy_force_name then
memory.scripted_biters [ entity.unit_number ] = nil
end
if entity.force . index == 3 or entity.force . name == ' environment ' then
if event.cause and event.cause . valid and event.cause . force.name == memory.enemy_force_name then
shred_nearby_simple_entities ( entity )
end
end
if event.entity and event.entity . valid and event.entity . force and event.entity . force.name == memory.force_name then
2023-01-11 22:15:55 +02:00
if memory.boat and memory.boat . cannonscount and entity.name == ' artillery-turret ' then
2021-10-13 10:21:53 +02:00
memory.boat . cannonscount = memory.boat . cannonscount - 1
-- if memory.boat.cannonscount <= 0 then
-- Crew.try_lose()
-- end
2022-05-29 13:36:27 +02:00
Crew.try_lose ( { ' pirates.loss_cannon_destroyed ' } )
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
if entity and entity.valid and entity.force and entity.force . name == memory.enemy_force_name then
if ( entity.name == ' biter-spawner ' or entity.name == ' spitter-spawner ' ) then
spawner_died ( event )
2022-03-17 03:40:18 +02:00
-- I think the only reason krakens don't trigger this right now is that they are destroyed rather than .die()
2021-10-13 10:21:53 +02:00
else
local destination = Common.current_destination ( )
if not ( destination and destination.dynamic_data and destination.dynamic_data . quest_type and ( not destination.dynamic_data . quest_complete ) ) then return end
if destination.dynamic_data . quest_type == Quest.enum . WORMS and entity.type == ' turret ' then
destination.dynamic_data . quest_progress = destination.dynamic_data . quest_progress + 1
Quest.try_resolve_quest ( )
end
end
end
end
2022-07-30 11:29:17 +02:00
function Public . research_apply_buffs ( event )
local memory = Memory.get_crew_memory ( )
local force = memory.force
if Balance.research_buffs [ event.research . name ] then
local tech = Balance.research_buffs [ event.research . name ]
-- @FIXME: This code is from another scenario but doesn't work
for k , v in pairs ( tech ) do
force [ k ] = force [ k ] + v
end
end
end
2021-10-13 10:21:53 +02:00
2022-03-10 23:09:06 +02:00
function Public . apply_flamer_nerfs ( )
2021-10-13 10:21:53 +02:00
local memory = Memory.get_crew_memory ( )
2022-03-19 23:20:55 +02:00
-- local difficulty = memory.difficulty
2022-03-04 19:57:58 +02:00
local force = memory.force
2022-03-09 01:36:03 +02:00
-- This code matches the vanilla game. Written by Hanakocz I think.
2021-10-13 10:21:53 +02:00
local flame_researches = {
[ 1 ] = { name = ' refined-flammables-1 ' , bonus = 0.2 } ,
[ 2 ] = { name = ' refined-flammables-2 ' , bonus = 0.2 } ,
[ 3 ] = { name = ' refined-flammables-3 ' , bonus = 0.2 } ,
[ 4 ] = { name = ' refined-flammables-4 ' , bonus = 0.3 } ,
[ 5 ] = { name = ' refined-flammables-5 ' , bonus = 0.3 } ,
[ 6 ] = { name = ' refined-flammables-6 ' , bonus = 0.4 } ,
[ 7 ] = { name = ' refined-flammables-7 ' , bonus = 0.2 }
}
local flamer_power = 0
for i = 1 , 6 , 1 do
if force.technologies [ flame_researches [ i ] . name ] . researched then
flamer_power = flamer_power + flame_researches [ i ] . bonus
end
end
flamer_power = flamer_power + ( force.technologies [ flame_researches [ 7 ] . name ] . level - 7 ) * 0.2
2022-03-10 23:09:06 +02:00
force.set_ammo_damage_modifier ( ' flamethrower ' , flamer_power * Balance.flamers_tech_multipliers ( ) + Balance.flamers_base_nerf ( ) )
force.set_turret_attack_modifier ( ' flamethrower-turret ' , flamer_power * Balance.flamers_tech_multipliers ( ) + Balance.flamers_base_nerf ( ) )
2021-10-13 10:21:53 +02:00
end
local function event_on_research_finished ( event )
-- figure out which crew this is about:
local research = event.research
local p_force = research.force
2022-06-15 23:00:18 +02:00
local crew_id = Common.get_id_from_force_name ( p_force.name )
2021-10-13 10:21:53 +02:00
Memory.set_working_id ( crew_id )
local memory = Memory.get_crew_memory ( )
2022-07-31 22:13:14 +02:00
if ( not ( memory.game_lost ) ) then --this condition should prevent discord messages being fired when the crew disbands and gets reset
-- using a localised string means we have to write this out (recall that "" signals concatenation)
memory.force . print ( { " " , ' >> ' , { ' pirates.research_notification ' , research.localised_name } } , CoreData.colors . notify_force_light )
2022-09-13 23:09:25 +02:00
2022-07-31 22:13:14 +02:00
Server.to_discord_embed_raw ( { ' ' , ' [ ' .. memory.name .. ' ] ' , { ' pirates.research_notification ' , game.technology_prototypes [ research.name ] . localised_name } } , true )
end
2021-10-13 10:21:53 +02:00
2022-03-10 23:09:06 +02:00
Public.apply_flamer_nerfs ( )
2023-01-29 23:01:48 +02:00
-- Public.research_apply_buffs(event) -- this is broken right now
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
for _ , e in ipairs ( research.effects ) do
local t = e.type
if t == ' ammo-damage ' then
local category = e.ammo_category
local factor = Balance.player_ammo_damage_modifiers ( ) [ category ]
if factor then
local current_m = p_force.get_ammo_damage_modifier ( category )
local m = e.modifier
p_force.set_ammo_damage_modifier ( category , current_m + factor * m )
end
elseif t == ' gun-speed ' then
local category = e.ammo_category
local factor = Balance.player_gun_speed_modifiers ( ) [ category ]
if factor then
local current_m = p_force.get_gun_speed_modifier ( category )
local m = e.modifier
p_force.set_gun_speed_modifier ( category , current_m + factor * m )
end
elseif t == ' turret-attack ' then
local category = e.ammo_category
local factor = Balance.player_turret_attack_modifiers ( ) [ category ]
if factor then
local current_m = p_force.get_turret_attack_modifier ( category )
local m = e.modifier
p_force.set_turret_attack_modifier ( category , current_m + factor * m )
end
end
end
2022-10-06 13:47:17 +02:00
Crew.disable_recipes ( p_force )
2021-10-13 10:21:53 +02:00
end
local function event_on_player_joined_game ( event )
local global_memory = Memory.get_global_memory ( )
local player = game.players [ event.player_index ]
2022-03-09 01:36:03 +02:00
--figure out if we should drop them back into a crew:
2021-10-13 10:21:53 +02:00
2022-05-29 13:36:27 +02:00
if ( not Server.get_current_time ( ) ) then -- don't run this on servers because I'd need to negotiate that with the rest of Comfy
2022-06-02 15:51:56 +02:00
player.print ( { ' pirates.thesixthroc_support_toast ' } , { r = 1 , g = 0.4 , b = 0.9 } )
2022-05-29 13:36:27 +02:00
end
2022-05-30 17:52:55 +02:00
2022-05-30 17:51:08 +02:00
if _DEBUG then
2022-06-01 20:50:36 +02:00
game.print ( ' Debug mode on. Use /go to get started, /1 /4 /32 etc to change game speed. ' )
2022-10-02 23:37:54 +02:00
game.print ( ' Current version: ' .. CoreData.version_string )
2022-05-30 17:51:08 +02:00
end
2022-05-29 13:36:27 +02:00
2022-03-09 01:36:03 +02:00
local crew_to_put_back_in = nil
2022-07-07 22:01:45 +02:00
for _ , memory in pairs ( global_memory.crew_memories ) do
2023-02-18 18:57:33 +02:00
if Common.is_id_valid ( memory.id ) and memory.crewstatus == Crew.enum . ADVENTURING and memory.temporarily_logged_off_characters [ player.index ] then
2022-07-07 22:01:45 +02:00
crew_to_put_back_in = memory.id
2022-03-09 01:36:03 +02:00
break
end
2021-10-13 10:21:53 +02:00
end
2022-03-09 01:36:03 +02:00
if crew_to_put_back_in then
2022-03-09 23:39:47 +02:00
Crew.join_crew ( player , crew_to_put_back_in , true )
2021-10-13 10:21:53 +02:00
2022-06-03 19:59:17 +02:00
local memory = global_memory.crew_memories [ crew_to_put_back_in ]
2023-02-02 21:44:44 +02:00
if ( not memory.run_is_protected ) and # memory.crewplayerindices <= 1 then
2023-02-18 18:57:33 +02:00
Roles.make_captain ( player )
2022-06-03 19:59:17 +02:00
end
2022-03-09 01:36:03 +02:00
if _DEBUG then log ( ' putting player back in their old crew ' ) end
else
if player.character and player.character . valid then
player.character . destroy ( )
end
player.set_controller ( { type = defines.controllers . god } )
player.create_character ( )
2022-03-19 23:20:55 +02:00
2022-03-09 01:36:03 +02:00
local spawnpoint = Common.lobby_spawnpoint
local surface = game.surfaces [ CoreData.lobby_surface_name ]
2022-03-19 23:20:55 +02:00
2022-03-09 01:36:03 +02:00
player.teleport ( surface.find_non_colliding_position ( ' character ' , spawnpoint , 32 , 0.5 ) or spawnpoint , surface )
Roles.add_player_to_permission_group ( player )
2022-03-19 23:20:55 +02:00
2022-03-09 01:36:03 +02:00
if not player.name then return end
2022-03-19 23:20:55 +02:00
2022-03-09 01:36:03 +02:00
-- start at Common.starting_island_spawnpoint or not?
2022-03-19 23:20:55 +02:00
2022-03-11 00:11:51 +02:00
if game.tick == 0 then
Common.ensure_chunks_at ( surface , spawnpoint , 5 )
end
2022-03-19 23:20:55 +02:00
2022-03-09 01:36:03 +02:00
-- Auto-join the oldest crew:
local ages = { }
2022-07-07 22:01:45 +02:00
for _ , memory in pairs ( global_memory.crew_memories ) do
if Common.is_id_valid ( memory.id )
2022-10-10 19:21:14 +02:00
and ( not memory.run_is_private )
2022-07-07 22:01:45 +02:00
and memory.crewstatus == Crew.enum . ADVENTURING
and memory.capacity
and memory.crewplayerindices
and # memory.crewplayerindices < memory.capacity
and ( not ( memory.tempbanned_from_joining_data
and memory.tempbanned_from_joining_data [ player.index ]
and game.tick < memory.tempbanned_from_joining_data [ player.index ] + Common.ban_from_rejoining_crew_ticks ) ) then
ages [ # ages + 1 ] = { id = memory.id , age = memory.age , large = ( memory.capacity >= Common.minimum_run_capacity_to_enforce_space_for ) }
2022-03-09 01:36:03 +02:00
end
end
table.sort (
ages ,
function ( a , b ) --true if a should be to the left of b
2022-03-29 01:36:38 +02:00
if a.large and ( not b.large ) then
return true
elseif ( not a.large ) and b.large then
return false
else
return a.age > b.age
end
2022-03-09 01:36:03 +02:00
end
)
if ages [ 1 ] then
Crew.join_crew ( player , ages [ 1 ] . id )
2022-06-03 19:59:17 +02:00
local memory = global_memory.crew_memories [ ages [ 1 ] . id ]
2023-02-02 21:44:44 +02:00
if ( not memory.run_is_protected ) and # memory.crewplayerindices <= 1 then
2023-02-18 18:57:33 +02:00
Roles.make_captain ( player )
2022-06-03 19:59:17 +02:00
end
2022-03-11 00:28:53 +02:00
if ages [ 2 ] then
2022-03-29 01:36:38 +02:00
if ages [ 1 ] . large and ( not ages [ # ages ] . large ) then
2022-05-29 13:36:27 +02:00
Common.notify_player_announce ( player , { ' pirates.goto_oldest_crew_with_large_capacity ' } )
2022-03-29 01:36:38 +02:00
else
2022-05-29 13:36:27 +02:00
Common.notify_player_announce ( player , { ' pirates.goto_oldest_crew ' } )
2022-03-29 01:36:38 +02:00
end
2022-03-11 00:28:53 +02:00
end
2023-02-02 21:44:44 +02:00
if memory.run_is_protected and ( not Roles.captain_exists ( ) ) then
Common.parrot_speak ( memory.force , { ' pirates.parrot_player_joins_protected_run_with_no_captain ' } )
Common.parrot_speak ( memory.force , { ' pirates.parrot_create_new_crew_tip ' } )
end
2022-03-11 00:11:51 +02:00
end
2021-10-13 10:21:53 +02:00
end
if not _DEBUG then
Gui.info . toggle_window ( player )
end
2022-06-02 15:07:17 +02:00
global_memory.last_players_health [ event.player_index ] = player.character . health
2021-10-13 10:21:53 +02:00
-- player.teleport(surface.find_non_colliding_position('character', spawnpoint, 32, 0.5), surface)
-- -- for item, amount in pairs(Balance.starting_items_player) do
-- -- player.insert({name = item, count = amount})
-- -- end
-- end
-- if player.surface.name ~= Common.current_destination().surface_name and string.sub(player.surface.name, 1, 10) ~= 'crowsnest-' then -- add other adventuring surfaces here
-- player.character = nil
-- player.set_controller({type=defines.controllers.god})
-- player.create_character()
2022-03-04 19:57:58 +02:00
-- player.teleport(surface.find_non_colliding_position('character', memory.force.get_spawn_position(surface), 32, 0.5), surface)
2021-10-13 10:21:53 +02:00
-- for item, amount in pairs(starting_items_player) do
-- player.insert({name = item, count = amount})
-- end
-- end
-- local tile = surface.get_tile(player.position)
-- if tile.valid then
-- if tile.name == 'out-of-map' then
2022-03-04 19:57:58 +02:00
-- player.teleport(surface.find_non_colliding_position('character', memory.force.get_spawn_position(surface), 32, 0.5), surface)
2021-10-13 10:21:53 +02:00
-- end
-- end
end
local function event_on_pre_player_left_game ( event )
local player = game.players [ event.player_index ]
local global_memory = Memory.get_global_memory ( )
-- figure out which crew this is about:
2022-06-15 23:00:18 +02:00
local crew_id = Common.get_id_from_force_name ( player.force . name )
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
for k , proposal in pairs ( global_memory.crewproposals ) do
2022-07-30 11:29:17 +02:00
if proposal and proposal.endorserindices then
for k2 , i in pairs ( proposal.endorserindices ) do
if i == event.player_index then
proposal.endorserindices [ k2 ] = nil
if # proposal.endorserindices == 0 then
proposal = nil
global_memory.crewproposals [ k ] = nil
end
2021-10-13 10:21:53 +02:00
end
end
end
end
2023-02-08 23:37:23 +02:00
if not Common.is_id_valid ( crew_id ) then
2021-10-13 10:21:53 +02:00
if player.character and player.character . valid then
player.character . destroy ( )
end
return -- nothing more needed
end
Memory.set_working_id ( crew_id )
local memory = Memory.get_crew_memory ( )
if player.controller_type == defines.controllers . editor then player.toggle_map_editor ( ) end
for _ , id in pairs ( memory.crewplayerindices ) do
if player.index == id then
2022-03-09 01:36:03 +02:00
Crew.leave_crew ( player , false , true )
2021-10-13 10:21:53 +02:00
break
end
end
for _ , id in pairs ( memory.spectatorplayerindices ) do
if player.index == id then
2022-02-26 20:25:48 +02:00
Crew.leave_spectators ( player , true )
2021-10-13 10:21:53 +02:00
break
end
end
2022-06-02 15:07:17 +02:00
global_memory.last_players_health [ event.player_index ] = nil
2021-10-13 10:21:53 +02:00
end
2022-03-19 23:20:55 +02:00
-- local function event_on_player_left_game(event)
-- -- n/a
-- end
2021-10-13 10:21:53 +02:00
-- local function on_player_changed_position(event)
-- local memory = Chrono_table.get_table()
-- if memory.planet[1].type.id == 14 then --lava planet
-- Event_functions.lava_planet(event)
-- end
-- end
2022-03-10 23:09:06 +02:00
2021-10-13 10:21:53 +02:00
local function on_player_changed_surface ( event )
local player = game.players [ event.player_index ]
2022-03-10 23:09:06 +02:00
local jailed = Jailed.get_jailed_table ( )
if player.name and jailed and jailed [ player.name ] then
-- not quite sure this is necessary, but let's send their items to the crew:
Common.send_important_items_from_player_to_crew ( player , true )
return
end
2022-03-12 13:51:11 +02:00
-- prevent connecting power between surfaces: (for the ship we do this automatically, but no need to let players do it in the general case:)
2022-03-12 00:53:36 +02:00
if not player.is_cursor_empty ( ) then
if player.cursor_stack and player.cursor_stack . valid_for_read then
local blacklisted = {
[ ' small-electric-pole ' ] = true ,
[ ' medium-electric-pole ' ] = true ,
[ ' big-electric-pole ' ] = true ,
[ ' substation ' ] = true ,
}
if blacklisted [ player.cursor_stack . name ] then
player.get_main_inventory ( ) . insert ( player.cursor_stack )
player.cursor_stack . clear ( )
end
end
if player.cursor_ghost then
player.cursor_ghost = nil
end
end
2022-02-26 20:25:48 +02:00
Roles.update_privileges ( player )
2021-10-13 10:21:53 +02:00
end
function Public . player_entered_vehicle ( player , vehicle )
if not vehicle then log ( ' no vehicle ' ) return end
-- if not vehicle.name then log('no vehicle') return end
-- if not vehicle.valid then log('vehicle invalid') return end
local player_relative_pos = { x = player.position . x - vehicle.position . x , y = player.position . y - vehicle.position . y }
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
local memory = Memory.get_crew_memory ( )
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
local player_boat_relative_pos
if memory and memory.boat and memory.boat . position then
player_boat_relative_pos = { x = player.position . x - memory.boat . position.x , y = player.position . y - memory.boat . position.y }
else
player_boat_relative_pos = { x = player.position . x - vehicle.position . x , y = player.position . y - vehicle.position . y }
end
local surfacedata = Surfaces.SurfacesCommon . decode_surface_name ( player.surface . name )
if vehicle.name == ' car ' then
2022-10-06 13:47:17 +02:00
-- A way to make player driven vehicles work
2022-06-15 23:00:18 +02:00
if vehicle.minable then
return
end
2021-10-13 10:21:53 +02:00
if surfacedata.type ~= Surfaces.enum . CROWSNEST and surfacedata.type ~= Surfaces.enum . CABIN and surfacedata.type ~= Surfaces.enum . LOBBY then
if player_boat_relative_pos.x < - 47 then
Surfaces.player_goto_cabin ( player , { x = 2 , y = player_relative_pos.y } )
else
Surfaces.player_goto_crows_nest ( player , player_relative_pos )
end
player.play_sound { path = " utility/picked_up_item " }
elseif surfacedata.type == Surfaces.enum . CROWSNEST then
Surfaces.player_exit_crows_nest ( player , player_relative_pos )
player.play_sound { path = " utility/picked_up_item " }
elseif surfacedata.type == Surfaces.enum . CABIN then
Surfaces.player_exit_cabin ( player , player_relative_pos )
player.play_sound { path = " utility/picked_up_item " }
end
vehicle.color = { 148 , 106 , 52 }
2022-10-06 13:47:17 +02:00
player.driving = false
2021-10-13 10:21:53 +02:00
elseif vehicle.name == ' locomotive ' then
if surfacedata.type ~= Surfaces.enum . HOLD and surfacedata.type ~= Surfaces.enum . LOBBY and Math.abs ( player_boat_relative_pos.y ) < 8 then --<8 in order not to enter holds of boats you haven't bought yet
Surfaces.player_goto_hold ( player , player_relative_pos , 1 )
player.play_sound { path = " utility/picked_up_item " }
elseif surfacedata.type == Surfaces.enum . HOLD then
local current_hold_index = surfacedata.destination_index
if current_hold_index >= memory.hold_surface_count then
Surfaces.player_exit_hold ( player , player_relative_pos )
else
Surfaces.player_goto_hold ( player , player_relative_pos , current_hold_index + 1 )
end
player.play_sound { path = " utility/picked_up_item " }
end
2022-10-06 13:47:17 +02:00
player.driving = false
end
2021-10-13 10:21:53 +02:00
end
local function event_on_player_driving_changed_state ( event )
local player = game.players [ event.player_index ]
local vehicle = event.entity
2022-06-15 23:00:18 +02:00
local crew_id = Common.get_id_from_force_name ( player.force . name )
2021-10-13 10:21:53 +02:00
Memory.set_working_id ( crew_id )
Public.player_entered_vehicle ( player , vehicle )
end
function Public . event_on_chunk_generated ( event )
local surface = event.surface
if not surface then return end
if not surface.valid then return end
if surface.name == ' nauvis ' or surface.name == ' piratedev1 ' or surface.name == ' gulag ' then return end
local seed = surface.map_gen_settings . seed
local name = surface.name
local surface_name_decoded = Surfaces.SurfacesCommon . decode_surface_name ( name )
local type = surface_name_decoded.type
2022-03-19 23:20:55 +02:00
-- local subtype = surface_name_decoded.subtype
2021-10-13 10:21:53 +02:00
local chunk_destination_index = surface_name_decoded.destination_index
local crewid = surface_name_decoded.crewid
Memory.set_working_id ( crewid )
local chunk_left_top = event.area . left_top
local width , height = nil , nil
local terraingen_coordinates_offset = { x = 0 , y = 0 }
local static_params = { }
2022-03-04 19:57:58 +02:00
local other_map_generation_data = { }
2021-10-13 10:21:53 +02:00
local scope
2023-02-19 18:57:38 +02:00
local overworldx = 0
2021-10-13 10:21:53 +02:00
local memory = Memory.get_crew_memory ( )
if type == Surfaces.enum . ISLAND and memory.destinations and memory.destinations [ chunk_destination_index ] then
local destination = memory.destinations [ chunk_destination_index ]
2022-10-02 23:37:54 +02:00
scope = Surfaces.get_scope ( surface_name_decoded )
2021-10-13 10:21:53 +02:00
static_params = destination.static_params
2022-03-04 19:57:58 +02:00
other_map_generation_data = destination.dynamic_data . other_map_generation_data or { }
2021-10-13 10:21:53 +02:00
terraingen_coordinates_offset = static_params.terraingen_coordinates_offset
width = static_params.width
height = static_params.height
2023-02-19 18:57:38 +02:00
overworldx = destination.overworld_position . x
2021-10-13 10:21:53 +02:00
end
if not scope then
scope = Surfaces [ type ]
end
local noise_params , terrain_fn , chunk_structures_fn
if scope then
if scope.Data then
if scope.Data . noiseparams then
noise_params = scope.Data . noiseparams
end
if ( not width ) and scope.Data . width then
width = scope.Data . width
end
if ( not height ) and scope.Data . height then
height = scope.Data . height
end
end
if scope.terrain then terrain_fn = scope.terrain end
if scope.chunk_structures then chunk_structures_fn = scope.chunk_structures end
end
if not width then
width = 999
log ( ' no surface width? ' .. type )
end
if not height then height = 999 end
local tiles , entities , decoratives , specials = { } , { } , { } , { }
-- local noise_generator = nil
local noise_generator = Utils.noise_generator ( noise_params , seed )
for y = 0.5 , 31.5 , 1 do
for x = 0.5 , 31.5 , 1 do
local p = { x = chunk_left_top.x + x , y = chunk_left_top.y + y }
if ( p.x >= - width / 2 and p.y >=- height / 2 and p.x <= width / 2 and p.y <= height / 2 ) then
2022-07-07 22:01:45 +02:00
terrain_fn {
p = Utils.psum { p , { 1 , terraingen_coordinates_offset } } ,
true_p = p ,
true_left_top = chunk_left_top ,
left_top = Utils.psum { chunk_left_top , { 1 , terraingen_coordinates_offset } } ,
noise_generator = noise_generator ,
static_params = static_params ,
tiles = tiles ,
entities = entities ,
decoratives = decoratives ,
specials = specials ,
seed = seed ,
other_map_generation_data = other_map_generation_data ,
2023-02-19 18:57:38 +02:00
iconized_generation = false ,
overworldx = overworldx ,
2022-07-07 22:01:45 +02:00
}
2021-10-13 10:21:53 +02:00
else
tiles [ # tiles + 1 ] = { name = ' out-of-map ' , position = Utils.psum { p , { 1 , terraingen_coordinates_offset } } }
end
end
end
2022-10-28 15:22:59 +02:00
if chunk_structures_fn then
chunk_structures_fn {
true_left_top = chunk_left_top ,
left_top = Utils.psum { chunk_left_top , { 1 , terraingen_coordinates_offset } } ,
noise_generator = noise_generator ,
static_params = static_params ,
specials = specials ,
entities = entities ,
seed = seed ,
other_map_generation_data = other_map_generation_data ,
biter_base_density_scale = Balance.biter_base_density_scale ( )
}
end
2021-10-13 10:21:53 +02:00
local tiles_corrected = { }
for i = 1 , # tiles do
local t = tiles [ i ]
t.position = Utils.psum { t.position , { - 1 , terraingen_coordinates_offset } }
tiles_corrected [ i ] = t
end
local correct_tiles = true --tile borders etc
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
if # tiles_corrected > 0 then surface.set_tiles ( tiles_corrected , correct_tiles ) end
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
local destination = Common.current_destination ( )
if destination.dynamic_data then
if not destination.dynamic_data . structures_waiting_to_be_placed then
destination.dynamic_data . structures_waiting_to_be_placed = { }
end
2022-06-18 16:45:38 +02:00
-- to avoid having chests on water, add a landfill tile underneath them
local landfill_tiles = { }
2021-10-13 10:21:53 +02:00
for _ , special in pairs ( specials ) do
-- recoordinatize:
special.position = Utils.psum { special.position , { - 1 , terraingen_coordinates_offset } }
2022-10-02 23:37:54 +02:00
if special.name == ' buried-treasure ' then
2021-10-13 10:21:53 +02:00
if destination.dynamic_data . buried_treasure and crewid ~= 0 then
destination.dynamic_data . buried_treasure [ # destination.dynamic_data . buried_treasure + 1 ] = { treasure = Loot.buried_treasure_loot ( ) , position = special.position }
end
2022-10-02 23:37:54 +02:00
elseif special.name == ' chest ' then
2022-06-15 23:00:18 +02:00
local e = surface.create_entity { name = ' wooden-chest ' , position = special.position , force = memory.ancient_friendly_force_name }
2021-10-13 10:21:53 +02:00
if e and e.valid then
e.minable = false
e.rotatable = false
e.destructible = false
2022-03-19 23:20:55 +02:00
2022-06-18 16:45:38 +02:00
local water_tiles = surface.find_tiles_filtered { position = special.position , radius = 0.1 , collision_mask = " water-tile " }
if water_tiles then
for _ , t in pairs ( water_tiles ) do
landfill_tiles [ # landfill_tiles + 1 ] = { name = " landfill " , position = t.position }
end
end
2021-10-13 10:21:53 +02:00
local inv = e.get_inventory ( defines.inventory . chest )
local loot = Loot.wooden_chest_loot ( )
for i = 1 , # loot do
local l = loot [ i ]
inv.insert ( l )
end
end
2022-10-02 23:37:54 +02:00
elseif special.name == ' market ' then
local e = surface.create_entity { name = ' market ' , position = special.position , force = memory.ancient_friendly_force_name }
if e and e.valid then
e.minable = false
e.rotatable = false
e.destructible = false
for _ , o in pairs ( special.offers ) do
e.add_market_item ( o )
end
end
2022-10-21 19:16:42 +02:00
elseif special.name == ' big-ship-wreck-2 ' or special.name == ' big-ship-wreck-1 ' then
local e = surface.create_entity { name = special.name , position = special.position , force = memory.ancient_friendly_force_name }
if e and e.valid then
e.minable = false
e.rotatable = false
e.destructible = false
local inv = e.get_inventory ( defines.inventory . chest )
2022-11-18 15:49:03 +02:00
local loot = Loot.iron_chest_loot ( )
2022-10-21 19:16:42 +02:00
for i = 1 , # loot do
local l = loot [ i ]
inv.insert ( l )
end
end
2021-10-13 10:21:53 +02:00
end
if special.components then
destination.dynamic_data . structures_waiting_to_be_placed [ # destination.dynamic_data . structures_waiting_to_be_placed + 1 ] = { data = special , tick = game.tick }
end
end
2022-06-18 16:45:38 +02:00
if # landfill_tiles > 0 then
surface.set_tiles ( landfill_tiles , true , false , false )
end
2021-10-13 10:21:53 +02:00
end
for i = 1 , # entities do
local e = entities [ i ]
e.position = Utils.psum { e.position , { - 1 , terraingen_coordinates_offset } }
local e2 = e
-- e2.build_check_type = defines.build_check_type.ghost_revive
2022-03-19 23:20:55 +02:00
-- log(_inspect(e2))
2023-01-29 17:30:59 +02:00
-- Allow placing worms in water in walkways
-- NOTE: Tile check there is to prevent worms from spawning outside island
if surface.can_place_entity ( e2 ) or ( destination.subtype == IslandEnum.enum . WALKWAYS and string.sub ( e.name , - 11 ) == ' worm-turret ' and surface.get_tile ( e.position . x , e.position . y ) . name == ' water-shallow ' ) then
2021-10-13 10:21:53 +02:00
local ee = surface.create_entity ( e )
if e.indestructible then
ee.destructible = false
end
end
end
local decoratives_corrected = { }
for i = 1 , # decoratives do
local d = decoratives [ i ]
d.position = Utils.psum { d.position , { - 1 , terraingen_coordinates_offset } }
decoratives_corrected [ i ] = d
end
if # decoratives_corrected > 0 then surface.create_decoratives { decoratives = decoratives_corrected } end
end
local function event_on_rocket_launched ( event )
-- figure out which crew this is about:
2022-06-15 23:00:18 +02:00
local crew_id = Common.get_id_from_force_name ( event.rocket . force.name )
2021-10-13 10:21:53 +02:00
Memory.set_working_id ( crew_id )
local memory = Memory.get_crew_memory ( )
local destination = Common.current_destination ( )
2023-01-30 17:19:45 +02:00
local rocket_launched_belongs_to_island = false
if destination.dynamic_data . rocketsilos then
for i = 1 , # destination.dynamic_data . rocketsilos do
if event.rocket_silo == destination.dynamic_data . rocketsilos [ i ] then
rocket_launched_belongs_to_island = true
break
end
end
end
-- We don't want to do anything if rocket was launched by silo that doesn't belong to island
-- NOTE: On rare occasions if rocket was launched but the silo died in the meantime, this will not give rewards to the crew (idk how to fix it though)
if not rocket_launched_belongs_to_island then return end
2021-10-13 10:21:53 +02:00
destination.dynamic_data . rocketlaunched = true
2022-02-24 21:39:03 +02:00
if memory.stored_fuel and destination.dynamic_data and destination.dynamic_data . rocketcoalreward then
memory.stored_fuel = memory.stored_fuel + destination.dynamic_data . rocketcoalreward
2022-05-06 14:00:57 +02:00
local a = Balance.rocket_launch_coin_reward
2022-05-29 13:36:27 +02:00
Common.give_items_to_crew ( { { name = ' coin ' , count = a } } )
2022-05-06 14:00:57 +02:00
memory.playtesting_stats . coins_gained_by_rocket_launches = memory.playtesting_stats . coins_gained_by_rocket_launches + a
2021-10-13 10:21:53 +02:00
end
2022-03-19 23:20:55 +02:00
2022-03-04 19:57:58 +02:00
local force = memory.force
2022-06-02 17:11:45 +02:00
local message = { ' pirates.granted_2 ' , { ' pirates.granted_rocket_launch ' } , Math.floor ( Balance.rocket_launch_coin_reward / 100 ) / 10 .. ' k [item=coin] ' , Math.floor ( destination.dynamic_data . rocketcoalreward / 100 ) / 10 .. ' k [item=coal] ' }
2022-05-29 13:36:27 +02:00
Common.notify_force_light ( force , message )
2021-10-13 10:21:53 +02:00
if destination.dynamic_data . quest_type == Quest.enum . TIME and ( not destination.dynamic_data . quest_complete ) then
destination.dynamic_data . quest_progressneeded = 1
Quest.try_resolve_quest ( )
end
if destination.dynamic_data . quest_type == Quest.enum . NODAMAGE and ( not destination.dynamic_data . quest_complete ) then
destination.dynamic_data . quest_progress = destination.dynamic_data . rocketsilohp
Quest.try_resolve_quest ( )
end
2022-06-02 14:36:44 +02:00
2022-06-02 16:32:27 +02:00
if destination.dynamic_data . rocketsilos then
for i = 1 , # destination.dynamic_data . rocketsilos do
local s = destination.dynamic_data . rocketsilos [ i ]
if s and s.valid then
2022-07-30 15:02:24 +02:00
s.destructible = true
2022-06-02 16:32:27 +02:00
s.die ( )
end
end
2022-06-02 14:36:44 +02:00
destination.dynamic_data . rocketsilos = nil
end
2021-10-13 10:21:53 +02:00
end
local function event_on_built_entity ( event )
local entity = event.created_entity
2022-06-15 23:00:18 +02:00
if not entity then return end
if not entity.valid then return end
2021-10-13 10:21:53 +02:00
2022-06-15 23:00:18 +02:00
if not event.player_index then return end
if not game.players [ event.player_index ] then return end
if not game.players [ event.player_index ] . valid then return end
local player = game.players [ event.player_index ]
local crew_id = Common.get_id_from_force_name ( player.force . name )
2021-10-13 10:21:53 +02:00
Memory.set_working_id ( crew_id )
local memory = Memory.get_crew_memory ( )
2022-06-15 23:00:18 +02:00
2021-10-13 10:21:53 +02:00
if entity.type == ' entity-ghost ' and entity.force and entity.force . valid then
entity.time_to_live = entity.force . ghost_time_to_live
end
2022-05-07 22:41:45 +02:00
if memory.boat and memory.boat . surface_name and player.surface == game.surfaces [ memory.boat . surface_name ] and entity.valid and entity.position then
2021-10-13 10:21:53 +02:00
if ( entity.type and ( entity.type == ' underground-belt ' ) ) or ( entity.name == ' entity-ghost ' and entity.ghost_type and ( entity.ghost_type == ' underground-belt ' ) ) then
2021-10-13 15:56:49 +02:00
if Boats.on_boat ( memory.boat , entity.position ) then
-- if (entity.type and (entity.type == 'underground-belt' or entity.type == 'pipe-to-ground')) or (entity.name == 'entity-ghost' and entity.ghost_type and (entity.ghost_type == 'underground-belt' or entity.ghost_type == 'pipe-to-ground')) then
if not ( entity.name and entity.name == ' entity-ghost ' ) then
player.insert { name = entity.name , count = 1 }
end
entity.destroy ( )
2022-05-29 13:36:27 +02:00
Common.notify_player_error ( player , { ' pirates.error_build_undergrounds_on_boat ' } )
2021-10-13 15:56:49 +02:00
return
2021-10-13 10:21:53 +02:00
end
end
end
-- hanas code for selective spidertrons:
-- local objective = Chrono_table.get_table()
-- if entity.name == 'spidertron' then
-- if objective.world.id ~= 7 or entity.surface.name == 'cargo_wagon' then
-- entity.destroy()
-- local player = game.players[event.player_index]
-- Alert.alert_player_warning(player, 8, {'chronosphere.spidertron_not_allowed'})
-- player.insert({name = 'spidertron', count = 1})
-- end
-- end
end
local function event_on_console_chat ( event )
if not ( event.message and event.player_index and game.players [ event.player_index ] ) then return end
local global_memory = Memory.get_global_memory ( )
local player = game.players [ event.player_index ]
local tag = player.tag
if not tag then
tag = ' '
end
local color = player.chat_color
-- if global.tournament_mode then
-- return
-- end
2022-06-15 23:00:18 +02:00
local crew_id = Common.get_id_from_force_name ( player.force . name )
2021-10-13 10:21:53 +02:00
Memory.set_working_id ( crew_id )
local memory = Memory.get_crew_memory ( )
2022-11-18 15:49:03 +02:00
-- NOTE: This check to see if player is in a crew is not reliable and can sometimes cause errors!
2022-06-15 23:00:18 +02:00
if player.force . name == ' player ' then
2021-10-13 10:21:53 +02:00
local other_force_indices = global_memory.crew_active_ids
for _ , index in pairs ( other_force_indices ) do
local recipient_force_name = global_memory.crew_memories [ index ] . force_name
game.forces [ recipient_force_name ] . print ( player.name .. tag .. ' [LOBBY]: ' .. event.message , color )
end
else
2022-11-18 15:49:03 +02:00
-- NOTE: For some reason memory.name(or player.name?) can be nil so need this check. It was observed it happened after crew died and resetted, then I said something in lobby before launching new run. That's the only recorded occurence so far.
if memory.name then
game.forces . player.print ( player.name .. tag .. ' [ ' .. memory.name .. ' ]: ' .. event.message , color )
else
game.forces . player.print ( player.name .. tag .. event.message , color )
log ( ' Error (non-critical): memory.name is nil ' )
end
2021-10-13 10:21:53 +02:00
end
end
local function event_on_market_item_purchased ( event )
Shop.event_on_market_item_purchased ( event )
end
local remove_boost_movement_speed_on_respawn =
Token.register (
function ( data )
local player = data.player
local crew_id = data.crew_id
2022-03-13 03:44:32 +02:00
if not ( player and player.valid ) then
2021-10-13 10:21:53 +02:00
return
end
2022-03-13 03:44:32 +02:00
-- their color was strobing, so now reset it to their chat color:
player.color = player.chat_color
2021-10-13 10:21:53 +02:00
Memory.set_working_id ( crew_id )
local memory = Memory.get_crew_memory ( )
2022-07-07 22:01:45 +02:00
if not Common.is_id_valid ( memory.id ) then return end --check if crew disbanded
2021-10-13 10:21:53 +02:00
if memory.game_lost then return end
2022-02-27 18:42:25 +02:00
memory.speed_boost_characters [ player.index ] = nil
2021-10-13 10:21:53 +02:00
2022-05-29 13:36:27 +02:00
Common.notify_player_expected ( player , { ' pirates.respawn_speed_bonus_removed ' } )
2021-10-13 10:21:53 +02:00
end
)
local boost_movement_speed_on_respawn =
Token.register (
function ( data )
local player = data.player
local crew_id = data.crew_id
if not player or not player.valid then
return
end
Memory.set_working_id ( crew_id )
local memory = Memory.get_crew_memory ( )
2022-07-07 22:01:45 +02:00
if not Common.is_id_valid ( memory.id ) then return end --check if crew disbanded
2021-10-13 10:21:53 +02:00
if memory.game_lost then return end
memory.speed_boost_characters [ player.index ] = true
2022-11-18 22:18:16 +02:00
Task.set_timeout_in_ticks ( 1200 , remove_boost_movement_speed_on_respawn , { player = player , crew_id = crew_id } )
2022-05-29 13:36:27 +02:00
Common.notify_player_expected ( player , { ' pirates.respawn_speed_bonus_applied ' } )
2021-10-13 10:21:53 +02:00
end
)
local function event_on_player_respawned ( event )
local player = game.players [ event.player_index ]
2022-06-15 23:00:18 +02:00
local crew_id = Common.get_id_from_force_name ( player.force . name )
2021-10-13 10:21:53 +02:00
Memory.set_working_id ( crew_id )
local memory = Memory.get_crew_memory ( )
local boat = memory.boat
if player.surface == game.surfaces [ Common.current_destination ( ) . surface_name ] then
2022-07-26 22:59:42 +02:00
if Boats.is_boat_at_sea ( ) then
2021-10-13 10:21:53 +02:00
-- assuming sea is always default:
local seasurface = game.surfaces [ memory.sea_name ]
player.teleport ( memory.spawnpoint , seasurface )
elseif boat and ( boat.state == Boats.enum_state . LANDED or boat.state == Boats.enum_state . RETREATING ) then
if player.character and player.character . valid then
Task.set_timeout_in_ticks ( 360 , boost_movement_speed_on_respawn , { player = player , crew_id = crew_id } )
2022-06-02 15:07:17 +02:00
local global_memory = Memory.get_global_memory ( )
global_memory.last_players_health [ event.player_index ] = player.character . health
2021-10-13 10:21:53 +02:00
end
end
end
2022-03-11 12:40:55 +02:00
end
2021-10-13 10:21:53 +02:00
2023-02-04 17:14:48 +02:00
local function event_on_entity_spawned ( event )
local entity = event.entity
if not entity then return end
if not entity.valid then return end
local surface = entity.surface
if not surface then return end
if not surface.valid then return end
local crew_id = SurfacesCommon.decode_surface_name ( surface.name ) . crewid
if not Common.is_id_valid ( crew_id ) then return end
Memory.set_working_id ( crew_id )
2023-02-19 15:05:34 +02:00
Common.try_make_biter_elite ( entity )
2023-02-04 17:14:48 +02:00
end
2021-10-13 10:21:53 +02:00
local event = require ' utils.event '
event.add ( defines.events . on_built_entity , event_on_built_entity )
event.add ( defines.events . on_entity_damaged , event_on_entity_damaged )
event.add ( defines.events . on_entity_died , event_on_entity_died )
2022-05-05 10:55:48 +02:00
-- event.add(defines.events.on_player_repaired_entity, event_on_player_repaired_entity)
2021-10-13 10:21:53 +02:00
event.add ( defines.events . on_player_joined_game , event_on_player_joined_game )
event.add ( defines.events . on_pre_player_left_game , event_on_pre_player_left_game )
2022-03-19 23:20:55 +02:00
-- event.add(defines.events.on_player_left_game, event_on_player_left_game)
2022-06-02 15:49:18 +02:00
-- event.add(defines.events.on_pre_player_mined_item, event_pre_player_mined_item)
2021-10-13 10:21:53 +02:00
event.add ( defines.events . on_player_mined_entity , event_on_player_mined_entity )
event.add ( defines.events . on_research_finished , event_on_research_finished )
event.add ( defines.events . on_player_changed_surface , on_player_changed_surface )
event.add ( defines.events . on_player_driving_changed_state , event_on_player_driving_changed_state )
-- event.add(defines.events.on_player_changed_position, event_on_player_changed_position)
-- event.add(defines.events.on_technology_effects_reset, event_on_technology_effects_reset)
2022-05-29 13:36:27 +02:00
-- event.add(defines.events.on_chunk_generated, PiratesApiEvents.on_chunk_generated) --moved to main in order to make the debug properties clear
2021-10-13 10:21:53 +02:00
event.add ( defines.events . on_rocket_launched , event_on_rocket_launched )
event.add ( defines.events . on_console_chat , event_on_console_chat )
event.add ( defines.events . on_market_item_purchased , event_on_market_item_purchased )
event.add ( defines.events . on_player_respawned , event_on_player_respawned )
2023-02-04 17:14:48 +02:00
event.add ( defines.events . on_entity_spawned , event_on_entity_spawned )
2021-10-13 10:21:53 +02:00
return Public