1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2026-04-28 21:04:39 +02:00
Files
2026-03-29 18:32:13 +02:00

417 lines
13 KiB
Lua

local Event = require 'utils.event'
local Token = require 'utils.token'
local Task = require 'utils.task'
local market_items = require 'modules.map_market_items'
local Global = require 'utils.global'
local Utils = require 'utils.utils'
local this =
{
enable_market = true,
turrets = {},
surface_name = 'nauvis'
}
Global.register(
this,
function (tbl)
this = tbl
end
)
local Public = {}
local random = math.random
local base_bp =
[[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]]
local force_name = 'defenders'
local tile_positions =
{
{ x = -3, y = -2 },
{ x = -3, y = -1 },
{ x = -3, y = 0 },
{ x = -3, y = 1 },
{ x = -3, y = 2 },
{ x = 3, y = -2 },
{ x = 3, y = -1 },
{ x = 3, y = 0 },
{ x = 3, y = 1 },
{ x = 3, y = 2 },
{ x = -2, y = -3 },
{ x = -1, y = -3 },
{ x = 0, y = -3 },
{ x = 1, y = -3 },
{ x = 2, y = -3 },
{ x = -2, y = 3 },
{ x = -1, y = 3 },
{ x = 0, y = 3 },
{ x = 1, y = 3 },
{ x = 2, y = 3 }
}
local global_offset = { x = 0, y = 0 }
local center_radius = 20
local p_tile = 'stone-path'
local concrete_tiles =
{
'refined-concrete',
'blue-refined-concrete',
'brown-refined-concrete',
'cyan-refined-concrete',
'green-refined-concrete',
'orange-refined-concrete',
'red-refined-concrete',
'yellow-refined-concrete'
}
local function shuffle(tbl)
local size = #tbl
for i = size, 1, -1 do
local rand = math.random(size)
tbl[i], tbl[rand] = tbl[rand], tbl[i]
end
return tbl
end
local function generate_random_tile()
local tile = concrete_tiles[random(1, #concrete_tiles)]
return tile
end
local function is_spawn(position)
if math.abs(position.x) > 32 then
return false
end
if math.abs(position.y) > 32 then
return false
end
local p = { x = position.x, y = position.y }
if p.x > 0 then
p.x = p.x + 1
end
if p.y > 0 then
p.y = p.y + 1
end
local d = math.sqrt(p.x ^ 2 + p.y ^ 2)
if d < 32 then
return true
end
end
local function create_force()
if not game.forces[force_name] then
game.create_force(force_name)
end
end
local function set_force_friendly()
create_force()
for _, force in pairs(game.forces) do
if force.name ~= 'enemy' then
local d = game.forces[force_name]
d.set_friend(force.name, true)
force.set_friend(d.name, true)
end
end
end
local function spawn_market()
if not this.enable_market then
return
end
if this.market and this.market.valid then
return
end
local get_surface = this.surface_name
local surface = game.surfaces[get_surface]
local pos = { { x = -10, y = -10 }, { x = 10, y = 10 }, { x = -10, y = -10 }, { x = 10, y = -10 } }
local _pos = shuffle(pos)
local p = surface.find_non_colliding_position('market', { _pos[1].x, _pos[1].y }, 60, 2)
this.market = surface.create_entity { name = 'market', position = p, force = 'neutral' }
rendering.draw_text
{
text = 'Spawn Market',
surface = surface,
target = { entity = this.market, offset = { 0, 2 } },
color = { r = 0.98, g = 0.66, b = 0.22 },
alignment = 'center'
}
this.market.destructible = false
local items = shuffle(market_items.spawn)
local space_age = script.active_mods['space-age']
for _, item in pairs(items) do
if not space_age then
item.offer.quality = 'normal'
end
this.market.add_market_item(item)
end
end
local spawn_market_token = Token.register(spawn_market)
local function spawn_area()
if this.spawn_generated then
return
end
this.spawn_generated = true
local get_surface = this.surface_name
local surface = game.surfaces[get_surface]
local offset = { x = -0, y = 0 }
local base_tiles = {}
local tiles = {}
for x = -center_radius, center_radius + 5 do
for y = -center_radius, center_radius + 5 do
if x ^ 2 + y ^ 2 < center_radius ^ 2 then
local tile = generate_random_tile()
base_tiles[#base_tiles + 1] = { name = tile, position = { x + offset.x, y + offset.y } }
local entities =
surface.find_entities_filtered
{
area = { { x + offset.x - 1, y + offset.y - 1 }, { x + offset.x, y + offset.y } }
}
for _, entity in pairs(entities) do
if entity.name ~= 'character' then
entity.destroy()
end
end
end
end
end
surface.set_tiles(base_tiles)
for _, position in pairs(tile_positions) do
table.insert(
tiles,
{
name = p_tile,
position = { position.x + offset.x + global_offset.x, position.y + offset.y + global_offset.y }
}
)
end
surface.set_tiles(tiles)
local positions = {}
for x = -center_radius, center_radius + 5 do
for y = -center_radius, center_radius + 5 do
if x ^ 2 + y ^ 2 < center_radius ^ 2 then
local position = { x = x, y = y }
if is_spawn(position) then
table.insert(positions, position)
end
end
end
end
shuffle(positions)
for _, position in pairs(positions) do
if surface.count_tiles_filtered({ area = { { position.x - 1, position.y - 1 }, { position.x + 2, position.y + 2 } }, name = 'black-refined-concrete' }) < 4 then
surface.set_tiles({ { name = 'black-refined-concrete', position = position } }, true)
end
end
create_force()
Public.build_from_blueprint(base_bp, global_offset, force_name, false)
end
local spawn_area_token = Token.register(spawn_area)
function Public.build_from_blueprint(bp_string, pos, force, flipped)
local surface_name = this.surface_name
local surface = game.get_surface(surface_name)
flipped = flipped or false
local bp_entity = game.surfaces.nauvis.create_entity { name = 'item-on-ground', position = { x = 0, y = 0 }, stack = 'blueprint' }
bp_entity.stack.import_stack(bp_string)
local direction = flipped and defines.direction.south or defines.direction.north
local entities = bp_entity.stack.build_blueprint { surface = surface, force = force, position = { x = pos.x, y = pos.y }, force_build = true, skip_fog_of_war = false, direction = direction }
bp_entity.destroy()
for _, e in pairs(entities) do
if e and e.valid then
if e.ghost_name == 'steel-chest' then
local entity = e.surface.create_entity { name = 'blue-chest', position = e.position, force = e.force }
if entity and entity.valid then
entity.destructible = false
entity.minable = false
entity.rotatable = false
entity.operable = false
end
else
local _, entity = e.silent_revive()
if entity and entity.valid then
entity.destructible = false
entity.minable = false
entity.rotatable = false
entity.operable = false
if entity.energy then
entity.energy = 100000000
end
if entity.name == 'gun-turret' then
entity.force = force_name
this.turrets[#this.turrets + 1] = entity
entity.insert({ name = 'uranium-rounds-magazine', count = 200 })
end
end
end
end
end
end
Event.add(
defines.events.on_force_created,
function ()
set_force_friendly()
end
)
Event.add(
defines.events.on_player_created,
function (event)
if event.player_index == 1 then
set_force_friendly()
Task.set_timeout_in_ticks(10, spawn_area_token)
Task.set_timeout_in_ticks(15, spawn_market_token)
end
end
)
Event.on_nth_tick(
350,
function ()
local tick = game.tick
if tick < 100 then
return
end
set_force_friendly()
if not this.market or not this.market.valid then
Task.set_timeout_in_ticks(15, spawn_market_token)
end
if next(this.turrets) then
for _, unit in pairs(this.turrets) do
if unit and unit.valid then
unit.insert({ name = 'uranium-rounds-magazine', count = 200 })
end
end
end
end
)
Event.add(
defines.events.on_robot_built_entity,
function (event)
local ce = event.entity
if not (ce and ce.valid) then
return
end
local surface_name = this.surface_name
if ce.surface.name ~= surface_name then
return
end
local area =
{
left_top = { x = ce.position.x - 12, y = ce.position.y - 12 },
right_bottom = { x = ce.position.x + 12, y = ce.position.y + 12 }
}
if Utils.contains_positions_only(tile_positions, area) then
ce.destroy()
end
end
)
Event.add(
defines.events.on_built_entity,
function (event)
local ce = event.entity
if not (ce and ce.valid) then
return
end
if event.player_index then
local player = game.get_player(event.player_index)
if player and player.valid and player.admin then return end
end
local surface_name = this.surface_name
if ce.surface.name ~= surface_name then
return
end
local area =
{
left_top = { x = ce.position.x - 12, y = ce.position.y - 12 },
right_bottom = { x = ce.position.x + 12, y = ce.position.y + 12 }
}
if Utils.contains_positions_only(tile_positions, area) then
ce.destroy()
end
end
)
Event.add(
{ defines.events.on_player_built_tile, defines.events.on_robot_built_tile },
function (event)
local ce = event.tiles
if not ce or not ce[1] then
return
end
local surface_index = event.surface_index
ce = ce[1]
local our_surface_index = this.surface_name
if surface_index ~= our_surface_index then
return
end
local area =
{
left_top = { x = ce.position.x - 12, y = ce.position.y - 12 },
right_bottom = { x = ce.position.x + 12, y = ce.position.y + 12 }
}
local surface = game.get_surface(surface_index)
local old_tile = ce.old_tile
if Utils.contains_positions_only(tile_positions, area) then
surface.set_tiles({ { name = old_tile.name, position = ce.position } }, true)
end
end
)
Public.spawn_area = spawn_area
Public.spawn_market = spawn_market
--- Sets surface name for spawn area to use
---@param name string
function Public.set_surface_name(name)
this.surface_name = name or 'nauvis'
end
return Public