--- Adds a custom spawn area with chests and afk turrets -- @addon Spawn-Area local Global = require 'utils.global' --- @dep utils.global local Event = require 'utils.event' --- @dep utils.event local config = require 'config.spawn_area' --- @dep config.spawn_area local turrets = config.turrets.locations Global.register(turrets, function(tbl) turrets = tbl end) -- Apply an offset to a LuaPosition local function apply_offset(position, offset) return { x = position.x + (offset.x or offset[1]), y = position.y + (offset.y or offset[2]) } end -- Apply the offset to the turrets default position for _, turret in ipairs(turrets) do turret.position = apply_offset(turret.position, config.turrets.offset) end -- Get or create the force used for entities in spawn local function get_spawn_force() local force = game.forces['Spawn'] if force and force.valid then return force end force = game.create_force('Spawn') force.set_cease_fire('player', true) game.forces['player'].set_cease_fire('Spawn', true) return force end -- Protects an entity and sets its force to the spawn force local function protect_entity(entity, set_force) if entity and entity.valid then entity.destructible = false entity.minable = false entity.rotatable = false entity.operable = false if not set_force then entity.health = 0 end if set_force then entity.force = get_spawn_force() end end end -- Will spawn all infinite ammo turrets and keep them refilled local function spawn_turrets() for _, turret_pos in pairs(turrets) do local surface = game.surfaces[turret_pos.surface] local pos = turret_pos.position local turret = surface.find_entity('gun-turret', pos) -- Makes a new turret if it is not found if not turret or not turret.valid then turret = surface.create_entity{name='gun-turret', position=pos, force='Spawn'} protect_entity(turret, true) end -- Adds ammo to the turret local inv = turret.get_inventory(defines.inventory.turret_ammo) if inv.can_insert{name=config.turrets.ammo_type, count=10} then inv.insert{name=config.turrets.ammo_type, count=10} end end end -- Makes a 2x2 afk belt at the locations in the config local function spawn_belts(surface, position) position = apply_offset(position, config.afk_belts.offset) local belt_type = config.afk_belts.belt_type local belt_details = {{-0.5, -0.5, 2}, {0.5, -0.5, 4}, {-0.5, 0.5, 0}, {0.5, 0.5, 6}} -- x, y,dir for _, belt_set in pairs(config.afk_belts.locations) do local set_position = apply_offset(position, belt_set) for _, belt in pairs(belt_details) do local pos = apply_offset(set_position, belt) local belt_entity = surface.create_entity{name=belt_type, position=pos, force='neutral', direction=belt[3]} if config.afk_belts.protected then protect_entity(belt_entity) end end end end -- Generates extra tiles in a set pattern set out in the config local function spawn_pattern(surface, position) position = apply_offset(position, config.pattern.offset) local tiles_to_make = {} local pattern_tile = config.pattern.pattern_tile for _, tile in pairs(config.pattern.locations) do table.insert(tiles_to_make, {name=pattern_tile, position=apply_offset(position, tile)}) end surface.set_tiles(tiles_to_make) end -- Generates extra water as set out in the config local function spawn_water(surface, position) position = apply_offset(position, config.water.offset) local tiles_to_make = {} local water_tile = config.water.water_tile for _, tile in pairs(config.water.locations) do table.insert(tiles_to_make, {name=water_tile, position=apply_offset(position, tile)}) end surface.set_tiles(tiles_to_make) end -- Generates the entities that are in the config local function spawn_entities(surface, position) position = apply_offset(position, config.entities.offset) for _, entity in pairs(config.entities.locations) do local pos = apply_offset(position, { x=entity[2], y=entity[3] }) entity = surface.create_entity{name=entity[1], position=pos, force='neutral'} if config.entities.protected then protect_entity(entity) end entity.operable = config.entities.operable end end -- Generates an area with no water or entities, no water area is larger local function spawn_area(surface, position) local dr = config.spawn_area.deconstruction_radius local dr2 = dr^2 local decon_tile = config.spawn_area.deconstruction_tile local fr = config.spawn_area.landfill_radius local fr2 = fr^2 local fill_tile = surface.get_tile(position).name -- Make sure a non water tile is used for each tile if surface.get_tile(position).collides_with('player-layer') then fill_tile = 'landfill' end if decon_tile == nil then decon_tile = fill_tile end local tiles_to_make = {} for x = -fr, fr do -- loop over x local x2 = (x+0.5)^2 for y = -fr, fr do -- loop over y local y2 = (y+0.5)^2 local dst = x2+y2 local pos = {x=position.x+x, y=position.y+y} if dst < dr2 then -- If it is inside the decon radius always set the tile table.insert(tiles_to_make, {name=decon_tile, position=pos}) elseif dst < fr2 and surface.get_tile(pos).collides_with('player-layer') then -- If it is inside the fill radius only set the tile if its water table.insert(tiles_to_make, {name=fill_tile, position=pos}) end end end -- Remove entities then set the tiles local entities_to_remove = surface.find_entities_filtered{position=position, radius=dr, name='character', invert=true} for _, entity in pairs(entities_to_remove) do entity.destroy() end surface.set_tiles(tiles_to_make) end -- Only add a event handler if the turrets are enabled if config.turrets.enabled then Event.on_nth_tick(config.turrets.refill_time, function() if game.tick < 10 then return end spawn_turrets() end) end -- When the first player joins create the spawn area Event.add(defines.events.on_player_created, function(event) if event.player_index ~= 1 then return end local player = game.players[event.player_index] local p = {x=0, y=0} local s = player.surface get_spawn_force() spawn_area(s, p) if config.pattern.enabled then spawn_pattern(s, p) end if config.water.enabled then spawn_water(s, p) end if config.afk_belts.enabled then spawn_belts(s, p) end if config.turrets.enabled then spawn_turrets() end if config.entities.enabled then spawn_entities(s, p) end player.teleport(p, s) end) -- Way to access global table return turrets