1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-01-10 00:43:27 +02:00
ComfyFactorio/maps/pirates/api_events.lua

1997 lines
77 KiB
Lua
Raw Normal View History

-- 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'
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'
2021-10-13 10:21:53 +02:00
local Islands = require 'maps.pirates.surfaces.islands.islands'
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'
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 = {}
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()
Crew.try_lose({'pirates.loss_silo_destroyed'})
2022-03-14 14:44:30 +02:00
elseif (not destination.dynamic_data.rocketlaunched) and destination.static_params and destination.static_params.base_cost_to_undock and destination.static_params.base_cost_to_undock['launch_rocket'] and destination.static_params.base_cost_to_undock['launch_rocket'] == true then
Crew.try_lose({'pirates.loss_silo_destroyed_before_necessary_launch'})
2022-03-05 02:11:11 +02:00
elseif (not destination.dynamic_data.rocketlaunched) then
Common.notify_force(force, {'pirates.silo_destroyed'})
2022-03-04 19:57:58 +02:00
end
2021-10-13 10:21:53 +02:00
end
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
-- 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
-- -- 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
-- -- manual 'resistance:'
-- local final_damage_amount2 = final_damage_amount / 4
2022-03-19 23:20:55 +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
-- 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)
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
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
2022-03-04 19:57:58 +02:00
if destination and destination.type and destination.subtype and destination.type == Surfaces.enum.ISLAND and destination.subtype == Islands.enum.MAZE then
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
-- 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
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()
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
local function damage_to_silo(event)
2021-10-13 10:21:53 +02:00
local memory = Memory.get_crew_memory()
local entity = event.entity
2021-10-13 10:21:53 +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()
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
2022-05-07 22:56:16 +02:00
if string.sub(event.cause.force.name, 1, 4) ~= 'crew' then
-- 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
if Common.entity_damage_healthbar(entity, event.original_damage_amount / Balance.silo_resistance_factor * (1 + Balance.biter_timeofday_bonus_damage(event.cause.surface.darkness))) <= 0 then
Public.silo_die()
else
destination.dynamic_data.rocketsilohp = memory.healthbars[entity.unit_number].health
2021-10-13 10:21:53 +02:00
end
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()
2022-03-15 20:50:19 +02:00
if memory.enemyboats and #memory.enemyboats > 0 then
if event.cause and event.cause.valid and event.entity and event.entity.valid then
if event.entity.force.name == memory.enemy_force_name then
2021-10-13 10:21:53 +02:00
for i = 1, #memory.enemyboats do
local eb = memory.enemyboats[i]
2022-03-15 20:50:19 +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
local adjusted_damage = damage
adjusted_damage = adjusted_damage / 2.6
2022-03-16 17:01:50 +02:00
2022-05-07 22:41:45 +02:00
-- if event.cause.name == 'artillery-turret' then
-- adjusted_damage = adjusted_damage / 1
-- end
2022-03-15 20:50:19 +02:00
if Common.entity_damage_healthbar(event.entity, adjusted_damage) <= 0 then
2022-03-15 20:50:19 +02:00
event.entity.die()
end
2021-10-13 10:21:53 +02:00
end
end
end
end
end
end
2022-03-14 14:44:30 +02:00
local function damage_to_artillery(event)
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
if (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
if event.cause.force.name ~= memory.enemy_force_name then return end
-- 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:
-- event.entity.health = event.entity.health + event.final_damage_amount - event.original_damage_amount
2022-06-03 15:15:42 +02:00
if Common.entity_damage_healthbar(event.entity, event.original_damage_amount / Balance.cannon_resistance_factor * (1 + Balance.biter_timeofday_bonus_damage(event.cause.surface.darkness)), Memory.get_crew_memory().boat) <= 0 then
event.entity.die()
end
2021-10-13 10:21:53 +02:00
else
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
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()
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
2021-10-13 10:21:53 +02:00
-- if event.cause.name == 'artillery-turret' then
2022-03-14 23:38:44 +02:00
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-03-10 23:09:06 +02:00
adjusted_damage = adjusted_damage / 1.1
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
adjusted_damage = adjusted_damage / 7 --laser turrets are in range. give some resistance
2022-03-03 02:19:20 +02:00
end
if Common.entity_damage_healthbar(event.entity, adjusted_damage) <= 0 then
2022-03-15 20:50:19 +02:00
Kraken.kraken_die(memory.healthbars[unit_number].id)
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-03-14 14:44:30 +02:00
local class = memory.classes_table and memory.classes_table[player_index]
local player = game.players[player_index]
if not (player and player.valid and player.character and player.character.valid) then
return
end
2022-03-04 19:57:58 +02:00
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
if class then
if class == Classes.enum.SCOUT then
damage_multiplier = damage_multiplier * Balance.scout_damage_taken_multiplier
-- 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
elseif class == Classes.enum.ROC_EATER then
damage_multiplier = damage_multiplier * Balance.roc_eater_damage_taken_multiplier
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
if Math.random() < chance then
-- only certain targets accept stickers
if 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
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
if event.cause.force.name == memory.enemy_force_name then
damage_multiplier = damage_multiplier * (1 + Balance.biter_timeofday_bonus_damage(event.cause.surface.darkness))
end --Enemy Forces
-- 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)
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
-- 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
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
local memory = Memory.get_crew_memory()
-- 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
if event.cause.force.name ~= memory.enemy_force_name then return end --Enemy Forces
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
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
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-03-14 14:44:30 +02:00
local class = memory.classes_table and memory.classes_table[player_index]
2021-10-13 10:21:53 +02:00
2022-03-14 14:44:30 +02:00
if class and class == Classes.enum.SCOUT and event.final_health > 0 then --lethal damage must be unaffected
2022-06-02 21:08:55 +02:00
event.entity.health = event.entity.health + (1 - Balance.scout_damage_dealt_multiplier) * event.final_damage_amount
2022-03-14 14:44:30 +02:00
elseif class and (class == Classes.enum.SAMURAI or class == Classes.enum.HATAMOTO) then
2022-03-07 11:50:25 +02:00
local samurai = memory.classes_table[player_index] == Classes.enum.SAMURAI
local hatamoto = memory.classes_table[player_index] == Classes.enum.HATAMOTO
2022-03-09 01:36:03 +02:00
--==Note this!
2022-03-07 11:50:25 +02:00
if not (samurai or hatamoto) then return end
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))
local melee = (physical or acid) and no_weapon
local extra_damage_to_deal = 0
local big_number = 1000
local extra_physical_damage_from_research_multiplier = 1 + memory.force.get_ammo_damage_modifier('bullet')
2022-06-02 21:08:55 +02:00
2022-03-07 11:50:25 +02:00
if melee and event.final_health > 0 then
if physical then
if samurai then
2022-06-03 22:58:10 +02:00
extra_damage_to_deal = Balance.samurai_damage_dealt_with_melee * extra_physical_damage_from_research_multiplier
2022-03-07 11:50:25 +02:00
elseif hatamoto then
2022-06-03 22:58:10 +02:00
extra_damage_to_deal = Balance.hatamoto_damage_dealt_with_melee * extra_physical_damage_from_research_multiplier
2022-03-07 11:50:25 +02:00
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.
2022-03-07 11:50:25 +02:00
extra_damage_to_deal = event.original_damage_amount * big_number
end
2022-03-09 01:36:03 +02:00
elseif (not melee) and event.final_health > 0 then
2022-06-02 21:08:55 +02:00
if samurai then
event.entity.health = event.entity.health + (1 - Balance.samurai_damage_dealt_when_not_melee_multiplier) * event.final_damage_amount
elseif hatamoto then
event.entity.health = event.entity.health + (1 - Balance.hatamoto_damage_dealt_when_not_melee_multiplier) * event.final_damage_amount
2022-03-09 01:36:03 +02:00
end
2021-10-13 10:21:53 +02:00
end
2022-03-04 19:57:58 +02:00
2022-03-07 11:50:25 +02:00
if extra_damage_to_deal > 0 then
2022-03-10 23:09:06 +02:00
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
2022-03-07 11:50:25 +02:00
else
local surplus = (extra_damage_to_deal - event.entity.health)*0.8
event.entity.die(character.force, character)
2022-03-10 23:09:06 +02:00
local nearest = player.surface.find_nearest_enemy{position = player.position, max_distance = 2, force = player.force}
if nearest and nearest.valid then
2022-03-07 11:50:25 +02:00
nearest.damage(surplus/big_number, character.force, 'acid', character)
end
end
2022-03-04 19:57:58 +02:00
end
end
2022-03-14 14:44:30 +02:00
if physical then
2022-03-04 19:57:58 +02:00
2022-03-14 14:44:30 +02:00
-- QUARTERMASTER BUFFS
2022-06-02 15:07:17 +02:00
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
2022-03-14 14:44:30 +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 memory.classes_table[p2_index] and memory.classes_table[p2_index] == Classes.enum.QUARTERMASTER then
event.entity.damage(Balance.quartermaster_bonus_physical_damage * event.final_damage_amount, character.force, 'impact', character) --triggers this function again, but not physical this time
2022-03-07 11:50:25 +02:00
end
2022-03-04 19:57:58 +02:00
end
end
2022-03-14 14:44:30 +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
2022-03-14 14:44:30 +02:00
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
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)
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()
if not (destination and destination.subtype and destination.subtype == Islands.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
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()
if not (destination and destination.subtype and destination.subtype == Islands.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
-- 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
-- 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
-- if event.entity.force.name ~= memory.enemy_force_name then return end
-- local evo = memory.evolution_factor
2022-03-28 01:40:32 +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
-- local surplus = evo - 1
2022-03-28 01:40:32 +02:00
-- local damage_multiplier = 1/(1 + Common.surplus_evo_biter_health_fractional_modifier(surplus))
2022-03-28 01:40:32 +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
-- -- 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
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
damage_to_silo(event)
damage_to_krakens(event)
damage_to_enemyboat_spawners(event)
if event.entity and event.entity.valid and event.entity.name and event.entity.name == 'artillery-turret' then
damage_to_artillery(event)
end
protect_special_entities(event)
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
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
-- 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
function Public.load_some_map_chunks_random_order(destination_index, 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
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 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
-- -- 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
local function event_on_player_mined_entity(event)
if not event.player_index then return end
local player = game.players[event.player_index]
if not player.valid then return end
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 destination = Common.current_destination()
local entity = event.entity
if not entity.valid then return end
2022-03-16 17:01:50 +02:00
if player.surface.name == 'gulag' then
event.buffer.clear()
return
end
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
if entity.type == 'tree' then
if not event.buffer then return end
local available = destination.dynamic_data.wood_remaining
local starting = destination.static_params.starting_wood
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
if available and destination.type == Surfaces.enum.ISLAND then
2022-03-04 19:57:58 +02:00
if destination and destination.subtype and destination.subtype == Islands.enum.MAZE then
if Math.random(1, 38) == 1 then
2022-03-04 20:24:04 +02:00
tick_tack_trap(memory.enemy_force_name, entity.surface, entity.position)
2022-03-04 19:57:58 +02:00
return
2022-03-01 23:59:48 +02:00
end
2022-03-14 14:44:30 +02:00
local give = {}
if memory.classes_table and memory.classes_table[event.player_index] then
if memory.classes_table[event.player_index] == Classes.enum.LUMBERJACK then
give[#give + 1] = {name = 'wood', count = 1}
2022-06-02 14:19:55 +02:00
Classes.lumberjack_bonus_items(give)
-- elseif memory.classes_table[event.player_index] == Classes.enum.WOOD_LORD then
-- give[#give + 1] = {name = 'wood', count = 1}
-- give[#give + 1] = {name = 'iron-ore', count = 1}
-- give[#give + 1] = {name = 'copper-ore', count = 1}
-- give[#give + 1] = {name = 'coal', count = 1}
-- if Math.random(every_nth_tree_gives_coins) == 1 then
-- local a = 12
-- 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
2022-03-14 14:44:30 +02:00
end
end
if #give > 0 then
Common.give(player, give, entity.position)
end
2022-03-01 23:59:48 +02:00
else
2022-03-04 19:57:58 +02:00
local give = {}
2022-03-19 23:20:55 +02:00
2022-03-04 19:57:58 +02:00
local baseamount = 4
--minimum 1 wood
2022-06-03 13:50:17 +02:00
local amount = Math.clamp(1, Math.max(1, Math.ceil(available)), Math.ceil(baseamount * available/starting))
2022-06-01 21:45:13 +02:00
2022-03-04 19:57:58 +02:00
destination.dynamic_data.wood_remaining = destination.dynamic_data.wood_remaining - amount
2022-03-19 23:20:55 +02:00
2022-03-04 19:57:58 +02:00
if memory.classes_table and memory.classes_table[event.player_index] and memory.classes_table[event.player_index] == Classes.enum.LUMBERJACK then
2022-06-02 14:19:55 +02:00
give[#give + 1] = {name = 'wood', count = amount}
Classes.lumberjack_bonus_items(give)
-- elseif memory.classes_table and memory.classes_table[event.player_index] and memory.classes_table[event.player_index] == Classes.enum.WOOD_LORD then
-- give[#give + 1] = {name = 'wood', count = amount + 3}
-- give[#give + 1] = {name = 'iron-ore', count = 1}
-- give[#give + 1] = {name = 'copper-ore', count = 1}
-- give[#give + 1] = {name = 'coal', count = 1}
-- if Math.random(every_nth_tree_gives_coins) == 1 then
-- local a = 12
-- 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
2022-03-04 19:57:58 +02:00
else
give[#give + 1] = {name = 'wood', count = amount}
2022-06-02 21:08:55 +02:00
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
2022-03-04 19:57:58 +02:00
end
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
Common.give(player, give, entity.position)
2021-10-13 10:21:53 +02:00
end
end
event.buffer.clear()
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
elseif entity.type == 'fish' then
if not event.buffer then return end
2022-03-04 19:57:58 +02:00
if memory.classes_table and memory.classes_table[event.player_index] and memory.classes_table[event.player_index] == Classes.enum.MASTER_ANGLER then
2022-06-02 15:07:17 +02:00
Common.give(player, {{name = 'raw-fish', count = Balance.base_caught_fish_amount + Balance.master_angler_fish_bonus}, {name = 'coin', count = Balance.master_angler_coin_bonus}}, entity.position)
2022-03-07 11:50:25 +02:00
elseif memory.classes_table and memory.classes_table[event.player_index] and memory.classes_table[event.player_index] == Classes.enum.DREDGER then
2022-06-02 15:07:17 +02:00
local to_give = {{name = 'raw-fish', count = Balance.base_caught_fish_amount + Balance.dredger_fish_bonus}}
2022-03-06 03:05:26 +02:00
to_give[#to_give + 1] = Loot.dredger_loot()[1]
Common.give(player, to_give, entity.position)
2022-03-04 19:57:58 +02:00
else
2022-06-02 15:07:17 +02:00
Common.give(player, {{name = 'raw-fish', count = Balance.base_caught_fish_amount}}, entity.position)
2022-03-04 19:57:58 +02:00
end
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
event.buffer.clear()
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
elseif entity.name == 'coal' or entity.name == 'stone' or entity.name == 'copper-ore' or entity.name == 'iron-ore' then
if not event.buffer then return end
local give = {}
2022-06-02 14:19:55 +02:00
if memory.overworldx > 0 then --no coins on first map, else the optimal strategy is to handmine everything there
2022-02-26 15:55:36 +02:00
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
2022-03-09 01:36:03 +02:00
give[#give + 1] = {name = entity.name, count = 6}
2022-03-04 19:57:58 +02:00
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
2022-03-07 22:15:47 +02:00
give[#give + 1] = {name = entity.name, count = 12}
2022-02-24 21:39:03 +02:00
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
2022-02-24 21:39:03 +02:00
end
give[#give + 1] = {name = entity.name, count = 2}
end
2022-02-26 15:55:36 +02:00
else
give[#give + 1] = {name = entity.name, count = 2}
2022-02-24 21:39:03 +02:00
end
2021-10-13 10:21:53 +02:00
Common.give(player, give, entity.position)
event.buffer.clear()
2022-03-19 23:20:55 +02:00
2021-10-13 10:21:53 +02:00
elseif entity.name == 'rock-huge' or entity.name == 'rock-big' or entity.name == 'sand-rock-big' then
if not event.buffer then return end
local available = destination.dynamic_data.rock_material_remaining
2022-03-19 23:20:55 +02:00
-- local starting = destination.static_params.starting_rock_material
2021-10-13 10:21:53 +02:00
if available and destination.type == Surfaces.enum.ISLAND then
2022-03-04 19:57:58 +02:00
if destination and destination.subtype and destination.subtype == Islands.enum.MAZE then
2022-03-13 20:19:59 +02:00
if Math.random(1, 35) == 1 then
2022-03-04 20:24:04 +02:00
tick_tack_trap(memory.enemy_force_name, entity.surface, entity.position)
2022-03-04 19:57:58 +02:00
return
2021-10-13 10:21:53 +02:00
end
2022-03-04 19:57:58 +02:00
else
local c = event.buffer.get_contents()
table.sort(c, function(a,b) return a.name < b.name end)
local c2 = {}
2022-03-19 23:20:55 +02:00
2022-03-04 19:57:58 +02:00
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}
end
2022-03-04 19:57:58 +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
2022-03-04 19:57:58 +02:00
end
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
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 = v, color = CoreData.colors.coal}
2022-03-04 19:57:58 +02:00
elseif k == 'stone' then
c2[#c2 + 1] = {name = k, count = v, color = CoreData.colors.stone}
2022-03-04 19:57:58 +02:00
end
end
Common.give(player, c2, entity.position)
2022-03-19 23:20:55 +02:00
2022-03-04 19:57:58 +02:00
destination.dynamic_data.rock_material_remaining = available
2022-03-19 23:20:55 +02:00
if Surfaces.get_scope(destination).break_rock then
Surfaces.get_scope(destination).break_rock(entity.surface, entity.position, entity.name)
end
2021-10-13 10:21:53 +02:00
end
end
event.buffer.clear()
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
local entity_name = entity.name
2021-10-13 10:21:53 +02:00
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
-- This gives enemy loot straight to combat robot owner's inventory instead of dropping it on the ground
if event.cause and (event.cause.name == 'defender' or event.cause.name == 'distractor' or event.cause.name == 'destroyer') then
if event.cause.combat_robot_owner and event.cause.combat_robot_owner.valid then
revenge_target = event.cause.combat_robot_owner
end
end
local class
if revenge_target and
revenge_target.valid and
revenge_target.player and
revenge_target.player.index and
memory.classes_table and
memory.classes_table[revenge_target.player.index]
then
class = memory.classes_table[revenge_target.player.index]
end
local class_is_chief = (class and class == Classes.enum.CHIEF) and true or false
-- no worm loot in the maze except for chiefs:
local maze = (destination.subtype and destination.subtype == Islands.enum.MAZE)
if maze and not (entity_name == 'biter-spawner' or entity_name == 'spitter-spawner') and not (class_is_chief) then return end
local iron_amount
local coin_amount
local fish_amount
if entity_name == 'small-worm-turret' then
iron_amount = 5
2022-06-02 13:57:15 +02:00
coin_amount = 50
fish_amount = 1 * Balance.chief_fish_received_for_worm_kill
memory.playtesting_stats.coins_gained_by_nests_and_worms = memory.playtesting_stats.coins_gained_by_nests_and_worms + coin_amount
elseif entity_name == 'medium-worm-turret' then
iron_amount = 20
2022-06-02 13:57:15 +02:00
coin_amount = 90
fish_amount = 1 * Balance.chief_fish_received_for_worm_kill
memory.playtesting_stats.coins_gained_by_nests_and_worms = memory.playtesting_stats.coins_gained_by_nests_and_worms + coin_amount
elseif entity_name == 'biter-spawner' or entity_name == 'spitter-spawner' then
iron_amount = 30
coin_amount = 100
fish_amount = 0 -- cooking spawners don't really fit class fantasy imo
memory.playtesting_stats.coins_gained_by_nests_and_worms = memory.playtesting_stats.coins_gained_by_nests_and_worms + coin_amount
elseif entity_name == 'big-worm-turret' then
iron_amount = 30
2022-06-02 13:57:15 +02:00
coin_amount = 140
fish_amount = 2 * Balance.chief_fish_received_for_worm_kill
memory.playtesting_stats.coins_gained_by_nests_and_worms = memory.playtesting_stats.coins_gained_by_nests_and_worms + coin_amount
elseif entity_name == 'behemoth-worm-turret' then
iron_amount = 50
2022-06-02 13:57:15 +02:00
coin_amount = 260
fish_amount = 3 * Balance.chief_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
fish_amount = 1 * Balance.chief_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
fish_amount = 1 * Balance.chief_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
fish_amount = 1 * Balance.chief_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
fish_amount = 1 * Balance.chief_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
fish_amount = 2 * Balance.chief_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
fish_amount = 2 * Balance.chief_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
fish_amount = 3 * Balance.chief_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
fish_amount = 3 * Balance.chief_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
local stack = {}
2021-10-13 10:21:53 +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
if class_is_chief and fish_amount and fish_amount > 0 then
stack[#stack + 1] = {name = 'raw-fish', count = fish_amount}
end
local short_form = (not iron_amount) and true or false
if revenge_target then
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
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
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
if memory.enemyboats then
for i = 1, #memory.enemyboats do
local eb = memory.enemyboats[i]
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)
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)
local memory = Memory.get_crew_memory()
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
if memory.enemyboats and #memory.enemyboats > 0 then
for i = 1, #memory.enemyboats do
local eb = memory.enemyboats[i]
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
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()
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
if memory.boat and memory.boat.cannonscount and entity.name and entity.name == 'artillery-turret' then
memory.boat.cannonscount = memory.boat.cannonscount - 1
-- if memory.boat.cannonscount <= 0 then
-- Crew.try_lose()
-- end
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-03-19 23:20:55 +02:00
-- function Public.research_apply_buffs(event)
-- local memory = Memory.get_crew_memory()
-- local force = memory.force
2021-10-13 10:21:53 +02:00
2022-03-19 23:20:55 +02:00
-- 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
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()
-- using a localised string means we have to write this out (recall that "" signals concatenation)
memory.force.print({"", '>> ', {'pirates.research_notification', event.research.localised_name}}, CoreData.colors.notify_force_light)
2021-10-13 10:21:53 +02:00
2022-03-10 23:09:06 +02:00
Public.apply_flamer_nerfs()
2022-03-19 23:20:55 +02:00
-- Public.research_apply_buffs(event) -- this is broken right now
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
-- even after research, force disable these:
-- p_force.recipes['underground-belt'].enabled = false
-- p_force.recipes['fast-underground-belt'].enabled = false
-- p_force.recipes['express-underground-belt'].enabled = false
p_force.recipes['pistol'].enabled = false
p_force.recipes['centrifuge'].enabled = false
2021-10-24 16:27:57 +02:00
-- p_force.recipes['flamethrower-turret'].enabled = false
2021-10-13 10:21:53 +02:00
p_force.recipes['locomotive'].enabled = false
p_force.recipes['car'].enabled = false
p_force.recipes['cargo-wagon'].enabled = false
2022-03-08 00:00:14 +02:00
p_force.recipes['slowdown-capsule'].enabled = false
2022-03-13 20:19:59 +02:00
p_force.recipes['nuclear-fuel'].enabled = false
2022-03-08 00:00:14 +02:00
-- p_force.recipes['rail'].enabled = false
p_force.recipes['speed-module'].enabled = false
p_force.recipes['tank'].enabled = false
p_force.recipes['cannon-shell'].enabled = false
p_force.recipes['explosive-cannon-shell'].enabled = false
-- and since we can't build tanks anyway, let's disable this for later:
p_force.recipes['uranium-cannon-shell'].enabled = false
p_force.recipes['explosive-uranium-cannon-shell'].enabled = false
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
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})
end
2022-05-30 17:52:55 +02:00
if _DEBUG then
game.print('Debug mode on. Use /go to get started, /1 /4 /32 etc to change game speed.')
end
2022-03-09 01:36:03 +02:00
local crew_to_put_back_in = nil
for _, memory in pairs(global_memory.crew_memories) do
if Common.is_id_valid(memory.id) and memory.crewstatus and memory.crewstatus == Crew.enum.ADVENTURING and memory.temporarily_logged_off_characters[player.index] then
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
local memory = global_memory.crew_memories[crew_to_put_back_in]
if #memory.crewplayerindices <= 1 then
memory.playerindex_captain = player.index
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 = {}
for _, memory in pairs(global_memory.crew_memories) do
if Common.is_id_valid(memory.id)
and memory.crewstatus
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)
local memory = global_memory.crew_memories[ages[1].id]
if #memory.crewplayerindices <= 1 then
memory.playerindex_captain = player.index
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
Common.notify_player_announce(player, {'pirates.goto_oldest_crew_with_large_capacity'})
2022-03-29 01:36:38 +02:00
else
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
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:
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
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
end
end
end
if not 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
-- a way to make simple cars work
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}
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
end
player.driving = false
end
local function event_on_player_driving_changed_state(event)
local player = game.players[event.player_index]
local vehicle = event.entity
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
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]
scope = Surfaces.get_scope(destination)
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
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
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,
iconized_generation = false
}
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
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()
}
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
-- 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}}
if special.name and special.name == 'buried-treasure' then
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
elseif special.name and special.name == 'chest' then
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
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
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
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))
2021-10-13 10:21:53 +02:00
if surface.can_place_entity(e2) then
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:
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()
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
local a = Balance.rocket_launch_coin_reward
Common.give_items_to_crew({{name = 'coin', count = a}})
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]'}
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
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
s.die()
end
end
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
if not entity then return end
if not entity.valid then return end
2021-10-13 10:21:53 +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()
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()
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
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()
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
game.forces.player.print(player.name .. tag .. ' [' .. memory.name .. ']: ' .. event.message, color)
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()
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
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()
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
Task.set_timeout_in_ticks(1050, remove_boost_movement_speed_on_respawn, {player = player, crew_id = crew_id})
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]
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-06-01 21:45:13 +02:00
if boat and boat.state == Boats.enum_state.ATSEA_SAILING or boat.state == Boats.enum_state.ATSEA_WAITING_TO_SAIL or boat.state == Boats.enum_state.ATSEA_LOADING_MAP 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
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)
-- 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)
-- 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)
return Public