You've already forked ComfyFactorio
mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2026-04-28 21:04:39 +02:00
417 lines
13 KiB
Lua
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
|