mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-01-10 00:43:27 +02:00
1560 lines
59 KiB
Lua
1560 lines
59 KiB
Lua
|
|
local boats = require "maps.pirates.structures.boats.boats"
|
|
local simplex_noise = require "utils.simplex_noise"
|
|
|
|
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 CoreData = require 'maps.pirates.coredata'
|
|
local Utils = require 'maps.pirates.utils_local'
|
|
local inspect = require 'utils.inspect'.inspect
|
|
local Ai = require 'maps.pirates.ai'
|
|
local Structures = require 'maps.pirates.structures.structures'
|
|
local Boats = require 'maps.pirates.structures.boats.boats'
|
|
local Surfaces = require 'maps.pirates.surfaces.surfaces'
|
|
local Progression = require 'maps.pirates.progression'
|
|
local Islands = require 'maps.pirates.surfaces.islands.islands'
|
|
local Roles = require 'maps.pirates.roles.roles'
|
|
local Gui = require 'maps.pirates.gui.gui'
|
|
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'
|
|
local Kraken = require 'maps.pirates.surfaces.sea.kraken'
|
|
|
|
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'
|
|
-- local Modifers = require 'player_modifiers'
|
|
|
|
local tick_tack_trap = require 'maps.pirates.from_comfy.tick_tack_trap' --'enemy' force, but that's okay
|
|
|
|
local Public = {}
|
|
|
|
function Public.silo_died()
|
|
local memory = Memory.get_crew_memory()
|
|
local destination = Common.current_destination()
|
|
local force = memory.force
|
|
if memory.game_lost == true then return end
|
|
|
|
destination.dynamic_data.rocketsilohp = 0
|
|
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
|
|
surface.create_entity({name = 'big-artillery-explosion', position = destination.dynamic_data.rocketsilos[1].position})
|
|
|
|
if memory.boat and memory.boat.surface_name and surface.name == memory.boat.surface_name then
|
|
|
|
if CoreData.rocket_silo_death_causes_loss then
|
|
-- Crew.lose_life()
|
|
Crew.try_lose('silo destroyed')
|
|
elseif (not destination.dynamic_data.rocketlaunched) and destination.static_params and destination.static_params.cost_to_leave and destination.static_params.cost_to_leave['launch_rocket'] and destination.static_params.cost_to_leave['launch_rocket'] == true then
|
|
Crew.try_lose('silo destroyed before a necessary launch')
|
|
elseif (not destination.dynamic_data.rocketlaunched) then
|
|
Common.notify_force(force, 'The silo was destroyed.')
|
|
end
|
|
end
|
|
|
|
destination.dynamic_data.rocketsilos[1].destroy()
|
|
destination.dynamic_data.rocketsilos = nil
|
|
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()
|
|
|
|
-- 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
|
|
|
|
-- manual 'resistance:'
|
|
local final_damage_amount2 = Utils.deepcopy(final_damage_amount) / 5
|
|
|
|
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
|
|
|
|
if destination.dynamic_data.rocketsilohp <= 0 then
|
|
-- if destination.dynamic_data.rocketsilohp <= 0 and (not destination.dynamic_data.rocketlaunched) then
|
|
Public.silo_died()
|
|
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
|
|
|
|
|
|
local function biters_chew_stuff_faster(event)
|
|
local memory = Memory.get_crew_memory()
|
|
local destination = Common.current_destination()
|
|
|
|
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 string.sub(event.cause.force.name, 1, 5) ~= 'enemy' then return end --Enemy Forces only
|
|
|
|
if (event.entity.force.index == 3 or event.entity.force.name == 'environment') then
|
|
event.entity.health = event.entity.health - event.final_damage_amount * 5
|
|
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
|
|
elseif event.entity.name == 'pipe' then
|
|
event.entity.health = event.entity.health - event.final_damage_amount * 0.5
|
|
elseif event.entity.name == 'stone-furnace' then
|
|
event.entity.health = event.entity.health - event.final_damage_amount * 0.5
|
|
elseif event.entity.name == 'wooden-chest' or event.entity.name == 'stone-chest' or event.entity.name == 'steel-chest' then
|
|
event.entity.health = event.entity.health - event.final_damage_amount * 0.5
|
|
end
|
|
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
|
|
end
|
|
|
|
|
|
local function silo_damage(event)
|
|
local memory = Memory.get_crew_memory()
|
|
|
|
if event.cause and event.cause.valid and event.entity and event.entity.valid then
|
|
if event.entity.force.name == memory.force_name then
|
|
local surfacedata = Surfaces.SurfacesCommon.decode_surface_name(event.entity.surface.name)
|
|
local dest = Common.current_destination()
|
|
if surfacedata.type == Surfaces.enum.CROWSNEST or surfacedata.type == Surfaces.enum.LOBBY then
|
|
event.entity.health = event.entity.health + event.final_damage_amount
|
|
elseif dest.dynamic_data.rocketsilos and dest.dynamic_data.rocketsilos[1] and dest.dynamic_data.rocketsilos[1].valid and event.entity == Common.current_destination().dynamic_data.rocketsilos[1] then
|
|
event.entity.health = event.entity.health + event.final_damage_amount
|
|
if string.sub(event.cause.force.name, 1, 4) ~= 'crew' then
|
|
Public.damage_silo(event.original_damage_amount)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
local function enemyboat_spawners_invulnerable(event)
|
|
local memory = Memory.get_crew_memory()
|
|
|
|
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
|
|
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 and eb.state == Structures.Boats.enum_state.APPROACHING then
|
|
event.entity.health = event.entity.health + event.final_damage_amount
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function artillery_damage(event)
|
|
local memory = Memory.get_crew_memory()
|
|
|
|
if not (event.entity and event.entity.valid and event.entity.name and event.entity.name == 'artillery-turret') then return end
|
|
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 string.sub(event.cause.force.name, 1, 5) ~= 'enemy' then return end
|
|
-- remove resistances:
|
|
event.entity.health = event.entity.health + event.final_damage_amount - event.original_damage_amount
|
|
else
|
|
event.entity.health = event.entity.health + event.final_damage_amount --nothing else should damage it
|
|
end
|
|
end
|
|
|
|
local function kraken_damage(event)
|
|
local memory = Memory.get_crew_memory()
|
|
|
|
if not (event.entity and event.entity.valid and event.entity.name and event.entity.name == 'biter-spawner') then return end
|
|
if not event.cause then return end
|
|
if not event.cause.valid then return end
|
|
if not event.cause.name then return end
|
|
|
|
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
|
|
|
|
if event.damage_type.name and (event.damage_type.name == 'explosion' or event.damage_type.name == 'poison') then
|
|
-- if event.cause.name == 'artillery-turret' then
|
|
adjusted_damage = adjusted_damage / 3
|
|
end
|
|
-- and additionally:
|
|
if event.cause.name == 'artillery-turret' then
|
|
adjusted_damage = adjusted_damage / 1.2
|
|
end
|
|
|
|
if event.damage_type.name and (event.damage_type.name == 'laser') then
|
|
adjusted_damage = adjusted_damage / 10 --laser turrets are in range
|
|
end
|
|
|
|
local healthbar = memory.healthbars[unit_number]
|
|
if not healthbar then return end
|
|
|
|
event.entity.health = 350 --set to full hp
|
|
local new_health = healthbar.health - adjusted_damage
|
|
healthbar.health = new_health
|
|
Common.update_healthbar_rendering(healthbar, new_health)
|
|
|
|
if new_health < 0 then
|
|
Kraken.kraken_die(healthbar.id)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
local function extra_damage_to_players(event)
|
|
local memory = Memory.get_crew_memory()
|
|
|
|
if not (event.entity and event.entity.valid and event.entity.name and event.entity.name == 'character') then return end
|
|
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.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 string.sub(event.cause.force.name, 1, 5) ~= 'enemy' then return end --Enemy Forces
|
|
|
|
local player_index = event.entity.player.index
|
|
if memory.classes_table and memory.classes_table[player_index] then
|
|
if memory.classes_table[player_index] == Classes.enum.MERCHANT then
|
|
event.entity.health = event.entity.health - event.final_damage_amount * 0.5
|
|
elseif memory.classes_table[player_index] == Classes.enum.SCOUT then
|
|
event.entity.health = event.entity.health - event.final_damage_amount * 0.2
|
|
elseif memory.classes_table[player_index] == Classes.enum.IRON_LEG and event.final_health > 0 then --lethal damage is unaffected, as otherwise they can never die
|
|
local inv = event.entity.get_inventory(defines.inventory.character_main)
|
|
if not (inv and inv.valid) then return end
|
|
local count = inv.get_item_count('iron-ore')
|
|
if count and count >= 2500 then
|
|
event.entity.health = event.entity.health + event.final_damage_amount * 0.75
|
|
end
|
|
end --samurai health buff is elsewhere
|
|
end
|
|
|
|
event.entity.health = event.entity.health - event.final_damage_amount * Balance.bonus_damage_to_humans()
|
|
end
|
|
|
|
|
|
local function scout_damage_dealt_changes(event)
|
|
local memory = Memory.get_crew_memory()
|
|
|
|
local player_index = event.cause.player.index
|
|
if memory.classes_table and memory.classes_table[player_index] and memory.classes_table[player_index] == Classes.enum.SCOUT then
|
|
if event.final_health > 0 then --lethal damage is unaffected, as otherwise they can never kill
|
|
event.entity.health = event.entity.health + 0.4 * event.final_damage_amount
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
local function samurai_damage_dealt_changes(event)
|
|
local memory = Memory.get_crew_memory()
|
|
|
|
local character = event.cause
|
|
local player = character.player
|
|
|
|
local player_index = player.index
|
|
|
|
if memory.classes_table and memory.classes_table[player_index] then
|
|
local samurai = memory.classes_table[player_index] == Classes.enum.SAMURAI
|
|
local hatamoto = memory.classes_table[player_index] == Classes.enum.HATAMOTO
|
|
|
|
if not (samurai or hatamoto) then return end
|
|
|
|
local physical = event.damage_type.name == 'physical'
|
|
local acid = event.damage_type.name == 'acid'
|
|
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
|
|
|
|
if melee and event.final_health > 0 then
|
|
if physical then
|
|
if samurai then
|
|
extra_damage_to_deal = 25
|
|
elseif hatamoto then
|
|
extra_damage_to_deal = 40
|
|
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. it assumes that characters only deal acid damage via this function.
|
|
extra_damage_to_deal = event.original_damage_amount * big_number
|
|
end
|
|
end
|
|
|
|
if extra_damage_to_deal > 0 then
|
|
if event.entity.health > extra_damage_to_deal then
|
|
event.entity.health = event.entity.health - extra_damage_to_deal
|
|
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 = {x = player.position.x, y = player.position.y}, max_distance = 2, force = character.force}
|
|
if nearest then
|
|
nearest.damage(surplus/big_number, character.force, 'acid', character)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
local function quartermaster_damage_dealt_changes(event)
|
|
local memory = Memory.get_crew_memory()
|
|
if not memory.classes_table then return end
|
|
|
|
if event.damage_type.name ~= 'physical' then return end
|
|
|
|
local character = event.cause
|
|
if not character.valid then return end
|
|
local player = character.player
|
|
local player_index = player.index
|
|
|
|
local nearby_players = player.surface.find_entities_filtered{position = player.position, radius = Common.quartermaster_range, type = {'character'}}
|
|
|
|
for _, p2 in pairs(nearby_players) do
|
|
if p2.player and p2.player.valid then
|
|
local p2_index = p2.player.index
|
|
if player_index ~= p2_index and memory.classes_table[p2_index] and memory.classes_table[p2_index] == Classes.enum.QUARTERMASTER then
|
|
if event.damage_type.name == 'physical' then
|
|
event.entity.damage(0.1 * event.original_damage_amount, character.force, 'impact', character) --triggers this function again, but not physical this time
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
local function swamp_resist_poison(event)
|
|
local memory = Memory.get_crew_memory()
|
|
|
|
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
|
|
|
|
if not (destination.surface_name == entity.surface.name) then return end
|
|
|
|
if not ((entity.type and entity.type == 'tree') or (event.entity.force and string.sub(event.entity.force.name, 1, 5) == 'enemy')) then return end
|
|
|
|
local damage = event.final_damage_amount
|
|
event.entity.health = event.entity.health + damage
|
|
end
|
|
|
|
|
|
local function maze_walls_resistance(event)
|
|
local memory = Memory.get_crew_memory()
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
else
|
|
if string.sub(event.cause.force.name, 1, 4) ~= 'crew' then return end --player damage only
|
|
event.entity.health = event.entity.health + damage * 0.9
|
|
end
|
|
end
|
|
|
|
|
|
local function event_on_entity_damaged(event)
|
|
|
|
-- figure out which crew this is about:
|
|
local crew_id = nil
|
|
if not crew_id and event.entity.surface.valid then crew_id = tonumber(string.sub(event.entity.surface.name, 1, 3)) or nil end
|
|
if not crew_id and event.force.valid then crew_id = tonumber(string.sub(event.force.name, -3, -1)) or nil end
|
|
if not crew_id and event.entity.valid then crew_id = tonumber(string.sub(event.entity.force.name, -3, -1)) or nil end
|
|
Memory.set_working_id(crew_id)
|
|
|
|
local memory = Memory.get_crew_memory()
|
|
local difficulty = memory.difficulty
|
|
|
|
if not event.entity.valid then return end
|
|
silo_damage(event)
|
|
if not event.entity.valid then return end -- need to call again, silo might be dead
|
|
if not event.entity.health then return end
|
|
|
|
enemyboat_spawners_invulnerable(event)
|
|
biters_chew_stuff_faster(event)
|
|
extra_damage_to_players(event)
|
|
artillery_damage(event)
|
|
swamp_resist_poison(event)
|
|
maze_walls_resistance(event)
|
|
|
|
if string.sub(event.entity.force.name, 1, 5) == 'enemy' then
|
|
kraken_damage(event)
|
|
-- Balance.biter_immunities(event)
|
|
end
|
|
|
|
if not event.cause then return end
|
|
if not event.cause.valid then return end
|
|
if event.cause.name ~= 'character' then return end
|
|
|
|
scout_damage_dealt_changes(event)
|
|
samurai_damage_dealt_changes(event)
|
|
quartermaster_damage_dealt_changes(event)
|
|
|
|
if event.damage_type.name ~= 'physical' then return end --guns and melee... maybe more
|
|
|
|
local character = event.cause
|
|
if character.shooting_state.state == defines.shooting.not_shooting then return end
|
|
--@TODO: These might fail to be valid if player is dead or something
|
|
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 not weapon.valid_for_read or not ammo.valid_for_read then return end
|
|
if weapon.name ~= 'pistol' then return end
|
|
if ammo.name ~= 'firearm-magazine' and ammo.name ~= 'piercing-rounds-magazine' and ammo.name ~= 'uranium-rounds-magazine' then return end
|
|
if not event.entity.valid then return end
|
|
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
|
|
|
|
|
|
|
|
|
|
function Public.biter_immunities(event)
|
|
local memory = Memory.get_crew_memory()
|
|
-- local planet = memory.planet[1].type.id
|
|
-- if event.damage_type.name == 'fire' then
|
|
-- if planet == 14 then --lava planet
|
|
-- event.entity.health = event.entity.health + event.final_damage_amount
|
|
-- local fire = event.entity.stickers
|
|
-- if fire and #fire > 0 then
|
|
-- for i = 1, #fire, 1 do
|
|
-- if fire[i].sticked_to == event.entity and fire[i].name == 'fire-sticker' then fire[i].destroy() break end
|
|
-- end
|
|
-- end
|
|
-- -- else -- other planets
|
|
-- -- event.entity.health = Math.floor(event.entity.health + event.final_damage_amount - (event.final_damage_amount / (1 + 0.02 * memory.difficulty * memory.chronojumps)))
|
|
-- end
|
|
-- elseif event.damage_type.name == 'poison' then
|
|
-- if planet == 18 then --swamp planet
|
|
-- event.entity.health = event.entity.health + event.final_damage_amount
|
|
-- end
|
|
-- end
|
|
end
|
|
|
|
|
|
|
|
|
|
function Public.load_some_map_chunks(destination_index, fraction, force_load) --in a 'spear' from the left
|
|
--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.
|
|
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))
|
|
|
|
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
|
|
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.
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function Public.load_some_map_chunks_random_order(destination_index, fraction)
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 = tonumber(string.sub(game.players[event.player_index].force.name, -3, -1)) or nil end
|
|
Memory.set_working_id(crew_id)
|
|
local memory = Memory.get_crew_memory()
|
|
|
|
-- 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
|
|
|
|
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 game.players[event.player_index].valid then return end
|
|
local crew_id = tonumber(string.sub(game.players[event.player_index].force.name, -3, -1)) or nil
|
|
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
|
|
|
|
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
|
|
|
|
if available and destination.type == Surfaces.enum.ISLAND then
|
|
|
|
if destination and destination.subtype and destination.subtype == Islands.enum.MAZE then
|
|
if Math.random(1, 45) == 1 then
|
|
tick_tack_trap(memory.enemy_force_name, entity.surface, entity.position)
|
|
return
|
|
end
|
|
else
|
|
local give = {}
|
|
|
|
local baseamount = 4
|
|
--minimum 1 wood
|
|
local amount = Math.max(Math.ceil(Math.min(available, baseamount * available/starting)),1)
|
|
destination.dynamic_data.wood_remaining = destination.dynamic_data.wood_remaining - amount
|
|
|
|
if memory.classes_table and memory.classes_table[event.player_index] and memory.classes_table[event.player_index] == Classes.enum.LUMBERJACK then
|
|
give[#give + 1] = {name = 'wood', count = amount + 3}
|
|
if Math.random(7) == 1 then
|
|
give[#give + 1] = {name = 'coin', count = 15}
|
|
end
|
|
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(7) == 1 then
|
|
give[#give + 1] = {name = 'coin', count = 15}
|
|
end
|
|
else
|
|
give[#give + 1] = {name = 'wood', count = amount}
|
|
if Math.random(7) == 1 then --tuned
|
|
give[#give + 1] = {name = 'coin', count = 5}
|
|
end
|
|
end
|
|
|
|
Common.give(player, give, entity.position)
|
|
end
|
|
end
|
|
event.buffer.clear()
|
|
|
|
elseif entity.type == 'fish' then
|
|
if not event.buffer then return end
|
|
|
|
|
|
if memory.classes_table and memory.classes_table[event.player_index] and memory.classes_table[event.player_index] == Classes.enum.MASTER_ANGLER then
|
|
Common.give(player, {{name = 'raw-fish', count = 5}, {name = 'coin', count = 8}}, entity.position)
|
|
elseif memory.classes_table and memory.classes_table[event.player_index] and memory.classes_table[event.player_index] == Classes.enum.DREDGER then
|
|
local to_give = {{name = 'raw-fish', count = 5}, {name = 'coin', count = 10}}
|
|
to_give[#to_give + 1] = Loot.dredger_loot()[1]
|
|
Common.give(player, to_give, entity.position)
|
|
else
|
|
Common.give(player, {{name = 'raw-fish', count = 3}}, entity.position)
|
|
end
|
|
|
|
event.buffer.clear()
|
|
|
|
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 = {}
|
|
|
|
if memory.overworldx > 0 then
|
|
if memory.classes_table and memory.classes_table[event.player_index] and memory.classes_table[event.player_index] == Classes.enum.PROSPECTOR then
|
|
give[#give + 1] = {name = 'coin', count = 3}
|
|
give[#give + 1] = {name = entity.name, count = 7}
|
|
elseif memory.classes_table and memory.classes_table[event.player_index] and memory.classes_table[event.player_index] == Classes.enum.CHIEF_EXCAVATOR then
|
|
give[#give + 1] = {name = 'coin', count = 4}
|
|
give[#give + 1] = {name = entity.name, count = 12}
|
|
else
|
|
if memory.overworldx > 0 then
|
|
give[#give + 1] = {name = 'coin', count = 1}
|
|
end
|
|
give[#give + 1] = {name = entity.name, count = 2}
|
|
end
|
|
else
|
|
give[#give + 1] = {name = entity.name, count = 2}
|
|
end
|
|
|
|
Common.give(player, give, entity.position)
|
|
event.buffer.clear()
|
|
|
|
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
|
|
local starting = destination.static_params.starting_rock_material
|
|
|
|
if available and destination.type == Surfaces.enum.ISLAND then
|
|
|
|
if destination and destination.subtype and destination.subtype == Islands.enum.MAZE then
|
|
if Math.random(1, 45) == 1 then
|
|
tick_tack_trap(memory.enemy_force_name, entity.surface, entity.position)
|
|
return
|
|
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
|
|
c2[#c2 + 1] = {name = 'coin', count = 45, color = CoreData.colors.coin}
|
|
else
|
|
c2[#c2 + 1] = {name = 'coin', count = 30, color = CoreData.colors.coin}
|
|
end
|
|
end
|
|
|
|
for k, v in pairs(c) do
|
|
local color
|
|
if k == 'coal' then
|
|
color = CoreData.colors.coal
|
|
elseif k == 'stone' then
|
|
color = CoreData.colors.stone
|
|
end
|
|
|
|
local amount = Math.max(Math.min(available,Math.ceil(v * available/starting)),1)
|
|
--override, decided to remove this effect:
|
|
amount = v
|
|
|
|
c2[#c2 + 1] = {name = k, count = amount, color = color}
|
|
end
|
|
Common.give(player, c2, entity.position)
|
|
|
|
destination.dynamic_data.rock_material_remaining = available
|
|
|
|
Surfaces.get_scope(destination).break_rock(entity.surface, entity.position, entity.name)
|
|
end
|
|
end
|
|
|
|
event.buffer.clear()
|
|
end
|
|
end
|
|
|
|
local function shred_nearby_simple_entities(entity)
|
|
local memory = Memory.get_crew_memory()
|
|
if memory.evolution_factor < 0.25 then return end
|
|
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()
|
|
local destination = Common.current_destination()
|
|
local entity = event.entity
|
|
if not (entity and entity.valid) then return end
|
|
if not (event.force and event.force.valid) then return end
|
|
|
|
-- no worm loot in the maze:
|
|
local maze = (destination and destination.subtype and destination.subtype == Islands.enum.MAZE)
|
|
if maze and not (entity.name == 'biter-spawner' or entity.name == 'spitter-spawner') then return end
|
|
|
|
local revenge_target
|
|
if event.cause and event.cause.valid and event.cause.name == 'character' then
|
|
revenge_target = event.cause
|
|
end
|
|
|
|
local iron_amount = 0
|
|
local coin_amount = 0
|
|
|
|
if memory.overworldx > 0 then
|
|
if entity.name == 'small-worm-turret' then
|
|
iron_amount = 5
|
|
coin_amount = 40
|
|
elseif entity.name == 'medium-worm-turret' then
|
|
iron_amount = 20
|
|
coin_amount = 70
|
|
elseif entity.name == 'biter-spawner' or entity.name == 'spitter-spawner'
|
|
then
|
|
iron_amount = 30
|
|
coin_amount = 70
|
|
elseif entity.name == 'big-worm-turret'
|
|
then
|
|
iron_amount = 30
|
|
coin_amount = 100
|
|
elseif entity.name == 'behemoth-worm-turret'
|
|
then
|
|
iron_amount = 50
|
|
coin_amount = 200
|
|
end
|
|
end
|
|
|
|
if iron_amount > 0 then
|
|
local stack = {{name = 'iron-plate', count = iron_amount}, {name = 'coin', count = coin_amount}}
|
|
|
|
if revenge_target then
|
|
Common.give(event.cause.player, stack)
|
|
else
|
|
Common.give(nil, stack, entity.position, entity.surface)
|
|
end
|
|
end
|
|
|
|
if (entity.name == 'biter-spawner' or entity.name == 'spitter-spawner') and entity.position and entity.surface and entity.surface.valid then
|
|
--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
|
|
end
|
|
end
|
|
if boat_spawner then
|
|
Ai.revenge_group(entity.surface, entity.position, revenge_target, 'biter', 0.3, 2)
|
|
elseif entity.name == 'biter-spawner' then
|
|
Ai.revenge_group(entity.surface, entity.position, revenge_target, 'biter')
|
|
else
|
|
Ai.revenge_group(entity.surface, entity.position, revenge_target, 'spitter')
|
|
end
|
|
end
|
|
end
|
|
|
|
local function spawner_died(event)
|
|
local memory = Memory.get_crew_memory()
|
|
local destination = Common.current_destination()
|
|
|
|
local extra_evo = Balance.evolution_per_biter_base_kill()
|
|
Common.increment_evo(extra_evo)
|
|
|
|
if destination.dynamic_data then
|
|
destination.dynamic_data.evolution_accrued_nests = destination.dynamic_data.evolution_accrued_nests + extra_evo
|
|
end
|
|
end
|
|
|
|
local function event_on_entity_died(event)
|
|
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 = nil
|
|
if not crew_id and event.force.valid then crew_id = tonumber(string.sub(event.force.name, -3, -1)) or nil end
|
|
if not crew_id and entity.valid then crew_id = tonumber(string.sub(entity.force.name, -3, -1)) or nil end
|
|
Memory.set_working_id(crew_id)
|
|
local memory = Memory.get_crew_memory()
|
|
if memory.id == 0 then return end
|
|
|
|
base_kill_rewards(event)
|
|
|
|
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('cannon destroyed')
|
|
end
|
|
end
|
|
|
|
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)
|
|
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
|
|
|
|
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
|
|
|
|
|
|
function Public.flamer_nerfs()
|
|
local memory = Memory.get_crew_memory()
|
|
local difficulty = memory.difficulty
|
|
local force = memory.force
|
|
|
|
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
|
|
|
|
-- force.set_ammo_damage_modifier('flamethrower', flamer_power - Balance.flamers_nerfs_size(memory.chronojumps, difficulty))
|
|
-- force.set_turret_attack_modifier('flamethrower-turret', flamer_power - Balance.flamers_nerfs_size(memory.chronojumps, difficulty))
|
|
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 = tonumber(string.sub(p_force.name, -3, -1)) or nil
|
|
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({"", '>> ', event.research.localised_name, ' researched.'}, CoreData.colors.notify_force_light)
|
|
|
|
Public.flamer_nerfs()
|
|
Public.research_apply_buffs(event)
|
|
|
|
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
|
|
-- p_force.recipes['flamethrower-turret'].enabled = false
|
|
p_force.recipes['locomotive'].enabled = false
|
|
p_force.recipes['car'].enabled = false
|
|
p_force.recipes['cargo-wagon'].enabled = false
|
|
p_force.recipes['slowdown-capsule'].enabled = false
|
|
-- p_force.recipes['rail'].enabled = false
|
|
end
|
|
|
|
local function event_on_player_joined_game(event)
|
|
local global_memory = Memory.get_global_memory()
|
|
|
|
local player = game.players[event.player_index]
|
|
|
|
-- if not memory.flame_boots[event.player_index] then
|
|
-- memory.flame_boots[event.player_index] = {}
|
|
-- end
|
|
-- memory.flame_boots[event.player_index] = {fuel = 1}
|
|
-- if not memory.flame_boots[event.player_index].steps then memory.flame_boots[event.player_index].steps = {} end
|
|
|
|
if player.character and player.character.valid then
|
|
player.character.destroy()
|
|
end
|
|
player.set_controller({type=defines.controllers.god})
|
|
player.create_character()
|
|
|
|
local spawnpoint = Common.lobby_spawnpoint
|
|
local surface = game.surfaces[CoreData.lobby_surface_name]
|
|
|
|
player.teleport(surface.find_non_colliding_position('character', spawnpoint, 32, 0.5) or spawnpoint, surface)
|
|
Roles.add_player_to_permission_group(player)
|
|
|
|
if not player.name then return end
|
|
|
|
-- start at Common.starting_island_spawnpoint or not?
|
|
|
|
-- if player.online_time == 0 then
|
|
Common.ensure_chunks_at(surface, spawnpoint, 5)
|
|
|
|
|
|
|
|
-- Auto-join the oldest crew:
|
|
local ages = {}
|
|
for _, mem in pairs(global_memory.crew_memories) do
|
|
if mem.id and mem.crewstatus and mem.crewstatus == Crew.enum.ADVENTURING and mem.capacity and mem.crewplayerindices and #mem.crewplayerindices < mem.capacity and (not (mem.tempbanned_from_joining_data and mem.tempbanned_from_joining_data[player.index] and game.tick < mem.tempbanned_from_joining_data[player.index] + Common.ban_from_rejoining_crew_ticks)) then
|
|
ages[#ages+1] = {id = mem.id, age = mem.age}
|
|
end
|
|
end
|
|
table.sort(
|
|
ages,
|
|
function(a, b) --true if a should be to the left of b
|
|
return a.age > b.age
|
|
end
|
|
)
|
|
if ages[1] then
|
|
Crew.join_crew(player, ages[1].id)
|
|
end
|
|
|
|
Roles.confirm_captain_exists(player)
|
|
|
|
if not _DEBUG then
|
|
Gui.info.toggle_window(player)
|
|
end
|
|
|
|
-- 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()
|
|
-- player.teleport(surface.find_non_colliding_position('character', memory.force.get_spawn_position(surface), 32, 0.5), surface)
|
|
-- 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
|
|
-- player.teleport(surface.find_non_colliding_position('character', memory.force.get_spawn_position(surface), 32, 0.5), surface)
|
|
-- 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 = tonumber(string.sub(player.force.name, -3, -1)) or 0
|
|
|
|
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 crew_id == 0 then
|
|
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
|
|
Crew.leave_crew(player, true)
|
|
break
|
|
end
|
|
end
|
|
for _, id in pairs(memory.spectatorplayerindices) do
|
|
if player.index == id then
|
|
Crew.leave_spectators(player, true)
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
local function event_on_player_left_game(event)
|
|
-- n/a
|
|
end
|
|
|
|
-- 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
|
|
|
|
local function on_player_changed_surface(event)
|
|
local player = game.players[event.player_index]
|
|
Roles.update_privileges(player)
|
|
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}
|
|
|
|
local crew_id = tonumber(string.sub(player.force.name, -3, -1)) or nil
|
|
Memory.set_working_id(crew_id)
|
|
local memory = Memory.get_crew_memory()
|
|
|
|
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
|
|
|
|
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
|
|
|
|
-- figure out which crew this is about:
|
|
local crew_id = tonumber(string.sub(player.force.name, -3, -1)) or nil
|
|
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
|
|
local subtype = surface_name_decoded.subtype
|
|
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 = {}
|
|
local other_map_generation_data = {}
|
|
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
|
|
other_map_generation_data = destination.dynamic_data.other_map_generation_data or {}
|
|
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}
|
|
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()}
|
|
|
|
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
|
|
|
|
if #tiles_corrected > 0 then surface.set_tiles(tiles_corrected, correct_tiles) end
|
|
|
|
|
|
|
|
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
|
|
|
|
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 = string.format('ancient-friendly-%03d', memory.id)}
|
|
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)
|
|
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
|
|
|
|
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
|
|
-- log(inspect(e2))
|
|
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 = tonumber(string.sub(event.rocket.force.name, -3, -1)) or nil
|
|
Memory.set_working_id(crew_id)
|
|
local memory = Memory.get_crew_memory()
|
|
local destination = Common.current_destination()
|
|
|
|
destination.dynamic_data.rocketlaunched = true
|
|
if memory.stored_fuel and destination.dynamic_data and destination.dynamic_data.rocketcoalreward then
|
|
memory.stored_fuel = memory.stored_fuel + destination.dynamic_data.rocketcoalreward
|
|
Common.give_reward_items{{name = 'coin', count = Balance.rocket_launch_coin_reward}}
|
|
end
|
|
|
|
local force = memory.force
|
|
Common.notify_force_light(force,'Granted ' .. Balance.rocket_launch_coin_reward .. ' [item=coin] and ' .. destination.dynamic_data.rocketcoalreward .. ' fuel.')
|
|
|
|
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
|
|
end
|
|
|
|
|
|
|
|
local function event_on_built_entity(event)
|
|
local entity = event.created_entity
|
|
if not entity or not entity.valid then
|
|
return
|
|
end
|
|
|
|
local crew_id = nil
|
|
if event.player_index and game.players[event.player_index].valid then crew_id = tonumber(string.sub(game.players[event.player_index].force.name, -3, -1)) or nil end
|
|
Memory.set_working_id(crew_id)
|
|
local memory = Memory.get_crew_memory()
|
|
local player = game.players[event.player_index]
|
|
|
|
if entity.type == 'entity-ghost' and entity.force and entity.force.valid then
|
|
entity.time_to_live = entity.force.ghost_time_to_live
|
|
end
|
|
|
|
if memory.boat and memory.boat.surface_name and player.surface == game.surfaces[memory.boat.surface_name] and entity.position then
|
|
if (entity.type and (entity.type == 'underground-belt')) or (entity.name == 'entity-ghost' and entity.ghost_type and (entity.ghost_type == 'underground-belt')) then
|
|
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_error(player, 'Undergrounds can\'t be built on the boat, due to conflicts with the boat movement code.')
|
|
return
|
|
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 message_force_name = player.force.name
|
|
|
|
local crew_id = tonumber(string.sub(player.force.name, -3, -1)) or nil
|
|
Memory.set_working_id(crew_id)
|
|
local memory = Memory.get_crew_memory()
|
|
|
|
if message_force_name == 'player' then
|
|
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
|
|
if not (player and player.valid and player.character and player.character.valid) then
|
|
return
|
|
end
|
|
|
|
Memory.set_working_id(crew_id)
|
|
local memory = Memory.get_crew_memory()
|
|
if not (memory.id and memory.id > 0) then return end --check if crew disbanded
|
|
if memory.game_lost then return end
|
|
memory.speed_boost_characters[player.index] = nil
|
|
|
|
-- their color was strobing, so now reset it to their chat color:
|
|
player.color = player.chat_color
|
|
|
|
Common.notify_player_expected(player, 'Respawn speed bonus removed.')
|
|
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
|
|
if not player.character or not player.character.valid and player.character and player.character.valid then
|
|
return
|
|
end
|
|
|
|
Memory.set_working_id(crew_id)
|
|
local memory = Memory.get_crew_memory()
|
|
if not (memory.id and memory.id > 0) then return end --check if crew disbanded
|
|
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, 'Respawn speed bonus applied.')
|
|
end
|
|
)
|
|
|
|
|
|
local function event_on_player_respawned(event)
|
|
local player = game.players[event.player_index]
|
|
|
|
local crew_id = tonumber(string.sub(player.force.name, -3, -1)) or nil
|
|
|
|
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
|
|
if boat and boat.state == Boats.enum_state.ATSEA_SAILING then
|
|
-- 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})
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
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)
|
|
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)
|
|
event.add(defines.events.on_player_left_game, event_on_player_left_game)
|
|
event.add(defines.events.on_pre_player_mined_item, event_pre_player_mined_item)
|
|
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, Interface.on_chunk_generated) --moved to main in order to make the debug properties clear
|
|
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 |