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

655 lines
16 KiB
Lua
Raw Normal View History

2020-05-21 23:08:23 +02:00
local Token = require 'utils.token'
2020-06-25 17:59:16 +02:00
local Task = require 'utils.task'
2020-05-21 23:08:23 +02:00
local ICW = require 'maps.mountain_fortress_v3.icw.main'
local Event = require 'utils.event'
2020-07-14 21:50:56 +02:00
local Global = require 'utils.global'
local this = {
power_sources = {index = 1},
refill_turrets = {index = 1},
magic_crafters = {index = 1},
2020-07-28 11:24:16 +02:00
magic_fluid_crafters = {index = 1},
2020-08-09 20:31:50 +02:00
art_table = {index = 1},
surface_cleared = false
2020-07-14 21:50:56 +02:00
}
Global.register(
this,
function(t)
this = t
end
)
2020-05-21 23:08:23 +02:00
local Public = {}
2020-08-09 20:22:33 +02:00
local random = math.random
local floor = math.floor
local sqrt = math.sqrt
2020-05-21 23:08:23 +02:00
local magic_crafters_per_tick = 3
local magic_fluid_crafters_per_tick = 8
2020-07-28 11:24:16 +02:00
local artillery_target_entities = {
'character',
'tank',
'car',
'furnace',
2020-10-19 20:21:27 +02:00
'locomotive',
'cargo-wagon',
'fluid-wagon',
'artillery-wagon'
2020-07-28 11:24:16 +02:00
}
2020-05-21 23:08:23 +02:00
local function fast_remove(tbl, index)
local count = #tbl
if index > count then
return
elseif index < count then
tbl[index] = tbl[count]
end
tbl[count] = nil
end
local function do_refill_turrets()
2020-07-14 21:50:56 +02:00
local refill_turrets = this.refill_turrets
2020-05-21 23:08:23 +02:00
local index = refill_turrets.index
if index > #refill_turrets then
refill_turrets.index = 1
return
end
local turret_data = refill_turrets[index]
local turret = turret_data.turret
if not turret.valid then
fast_remove(refill_turrets, index)
return
end
refill_turrets.index = index + 1
local data = turret_data.data
if data.liquid then
turret.fluidbox[1] = data
elseif data then
turret.insert(data)
end
end
2020-11-25 20:55:51 +02:00
-- local function turret_died(event)
-- local entity = event.entity
-- if not entity or not entity.valid then
-- return
-- end
-- local number = entity.unit_number
-- if not number then
-- return
-- end
-- local power_sources = this.power_sources
-- local ps_data = power_sources[number]
-- if ps_data then
-- power_sources[number] = nil
-- --[[ local ps_entity = ps_data.entity
-- local ps_pole = ps_data.pole ]]
-- if ps_data and ps_data.valid then
-- ps_data.destroy()
-- end
-- --[[ if ps_pole and ps_pole.valid then
-- ps_pole.destroy()
-- end ]]
-- end
-- end
local function do_turret_energy()
2020-07-14 21:50:56 +02:00
local power_sources = this.power_sources
2020-05-21 23:08:23 +02:00
2020-11-25 20:55:51 +02:00
for index = 1, #power_sources do
local ps_data = power_sources[index]
if not (ps_data or ps_data.valid) then
fast_remove(power_sources, index)
return
2020-05-21 23:08:23 +02:00
end
2020-11-25 20:55:51 +02:00
if ps_data and ps_data.valid then
ps_data.energy = 0xfffff
2020-05-21 23:08:23 +02:00
end
end
end
local function do_magic_crafters()
2020-07-14 21:50:56 +02:00
local magic_crafters = this.magic_crafters
2020-05-21 23:08:23 +02:00
local limit = #magic_crafters
if limit == 0 then
return
end
local index = magic_crafters.index
for i = 1, magic_crafters_per_tick do
if index > limit then
index = 1
end
local data = magic_crafters[index]
local entity = data.entity
if not entity.valid then
fast_remove(magic_crafters, index)
limit = limit - 1
if limit == 0 then
return
end
else
index = index + 1
local tick = game.tick
local last_tick = data.last_tick
local rate = data.rate
local count = (tick - last_tick) * rate
local fcount = floor(count)
2020-11-17 13:45:27 +02:00
if fcount > 1 then
fcount = 1
end
2020-05-21 23:08:23 +02:00
if fcount > 0 then
entity.get_output_inventory().insert {name = data.item, count = fcount}
data.last_tick = tick - (count - fcount) / rate
end
end
end
magic_crafters.index = index
end
local function do_magic_fluid_crafters()
2020-07-14 21:50:56 +02:00
local magic_fluid_crafters = this.magic_fluid_crafters
2020-05-21 23:08:23 +02:00
local limit = #magic_fluid_crafters
if limit == 0 then
return
end
local index = magic_fluid_crafters.index
for i = 1, magic_fluid_crafters_per_tick do
if index > limit then
index = 1
end
local data = magic_fluid_crafters[index]
local entity = data.entity
if not entity.valid then
fast_remove(magic_fluid_crafters, index)
limit = limit - 1
if limit == 0 then
return
end
else
index = index + 1
local tick = game.tick
local last_tick = data.last_tick
local rate = data.rate
local count = (tick - last_tick) * rate
local fcount = floor(count)
if fcount > 0 then
local fluidbox_index = data.fluidbox_index
local fb = entity.fluidbox
local fb_data = fb[fluidbox_index] or {name = data.item, amount = 0}
fb_data.amount = fb_data.amount + fcount
fb[fluidbox_index] = fb_data
data.last_tick = tick - (count - fcount) / rate
end
end
end
magic_fluid_crafters.index = index
end
2020-07-28 11:24:16 +02:00
local artillery_target_callback =
Token.register(
function(data)
local position = data.position
local entity = data.entity
if not entity.valid then
return
end
local tx, ty = position.x, position.y
local pos = entity.position
local x, y = pos.x, pos.y
local dx, dy = tx - x, ty - y
local d = dx * dx + dy * dy
2020-11-17 13:45:27 +02:00
if d >= 1024 and d <= 441398 then -- 704 in depth~
2020-07-28 11:24:16 +02:00
entity.surface.create_entity {
name = 'artillery-projectile',
position = position,
target = entity,
2020-11-15 20:23:54 +02:00
force = 'enemy',
2020-07-28 11:24:16 +02:00
speed = 1.5
}
end
end
)
local function do_artillery_turrets_targets()
local art_table = this.art_table
local index = art_table.index
if index > #art_table then
art_table.index = 1
return
end
art_table.index = index + 1
local outpost = art_table[index]
local now = game.tick
if now - outpost.last_fire_tick < 480 then
return
end
local turrets = outpost.artillery_turrets
for i = #turrets, 1, -1 do
local turret = turrets[i]
if not turret.valid then
fast_remove(turrets, i)
end
end
local count = #turrets
if count == 0 then
fast_remove(art_table, index)
return
end
outpost.last_fire_tick = now
local turret = turrets[1]
local area = outpost.artillery_area
local surface = turret.surface
local entities = surface.find_entities_filtered {area = area, name = artillery_target_entities}
if #entities == 0 then
return
end
local position = turret.position
for i = 1, count do
2020-08-09 20:22:33 +02:00
local entity = entities[random(#entities)]
2020-07-28 11:24:16 +02:00
if entity and entity.valid then
local data = {position = position, entity = entity}
Task.set_timeout_in_ticks(i * 60, artillery_target_callback, data)
end
end
end
2020-06-25 17:59:16 +02:00
local function add_magic_crafter_output(entity, output, distance)
2020-07-14 21:50:56 +02:00
local magic_fluid_crafters = this.magic_fluid_crafters
local magic_crafters = this.magic_crafters
2020-06-25 17:59:16 +02:00
local rate = output.min_rate + output.distance_factor * distance
local fluidbox_index = output.fluidbox_index
local data = {
entity = entity,
last_tick = game.tick,
base_rate = rate,
rate = rate,
item = output.item,
fluidbox_index = fluidbox_index
}
if fluidbox_index then
magic_fluid_crafters[#magic_fluid_crafters + 1] = data
else
magic_crafters[#magic_crafters + 1] = data
end
end
2020-05-21 23:08:23 +02:00
local function tick()
do_refill_turrets()
do_magic_crafters()
do_magic_fluid_crafters()
2020-07-28 11:24:16 +02:00
do_artillery_turrets_targets()
2020-05-21 23:08:23 +02:00
end
2020-05-23 21:18:18 +02:00
Public.deactivate_callback =
2020-05-21 23:08:23 +02:00
Token.register(
2020-05-23 21:18:18 +02:00
function(entity)
2020-06-25 17:59:16 +02:00
if entity and entity.valid then
entity.active = false
entity.operable = false
entity.destructible = false
end
2020-05-23 21:18:18 +02:00
end
)
2020-05-21 23:08:23 +02:00
2020-05-23 21:18:18 +02:00
Public.neutral_force =
Token.register(
function(entity)
2020-06-25 17:59:16 +02:00
if entity and entity.valid then
entity.force = 'neutral'
end
2020-05-21 23:08:23 +02:00
end
)
2020-05-23 21:18:18 +02:00
Public.enemy_force =
2020-05-21 23:08:23 +02:00
Token.register(
function(entity)
2020-06-25 17:59:16 +02:00
if entity and entity.valid then
entity.force = 'enemy'
end
2020-05-21 23:08:23 +02:00
end
)
2020-05-23 21:18:18 +02:00
2020-05-21 23:08:23 +02:00
Public.active_not_destructible_callback =
Token.register(
function(entity)
2020-06-25 17:59:16 +02:00
if entity and entity.valid then
entity.active = true
entity.operable = false
entity.destructible = false
end
2020-05-21 23:08:23 +02:00
end
)
Public.disable_minable_callback =
Token.register(
function(entity)
2020-06-25 17:59:16 +02:00
if entity and entity.valid then
entity.minable = false
end
2020-05-21 23:08:23 +02:00
end
)
Public.disable_minable_and_ICW_callback =
Token.register(
function(entity)
2020-06-25 17:59:16 +02:00
if entity and entity.valid then
entity.minable = false
2020-11-04 18:14:30 +02:00
ICW.register_wagon(entity, true)
2020-06-25 17:59:16 +02:00
end
2020-05-21 23:08:23 +02:00
end
)
Public.disable_destructible_callback =
Token.register(
function(entity)
2020-06-25 17:59:16 +02:00
if entity and entity.valid then
entity.destructible = false
2020-08-04 12:10:15 +02:00
entity.minable = false
2020-06-25 17:59:16 +02:00
end
2020-05-21 23:08:23 +02:00
end
)
Public.disable_active_callback =
Token.register(
function(entity)
2020-06-25 17:59:16 +02:00
if entity and entity.valid then
entity.active = false
end
2020-05-21 23:08:23 +02:00
end
)
2020-06-25 17:59:16 +02:00
local disable_active_callback = Public.disable_active_callback
2020-05-23 21:18:18 +02:00
Public.refill_turret_callback =
Token.register(
function(turret, data)
2020-07-14 21:50:56 +02:00
local refill_turrets = this.refill_turrets
2020-05-23 21:18:18 +02:00
local callback_data = data.callback_data
turret.direction = 3
refill_turrets[#refill_turrets + 1] = {turret = turret, data = callback_data}
end
)
2020-07-28 11:24:16 +02:00
Public.refill_artillery_turret_callback =
Token.register(
function(turret, data)
local refill_turrets = this.refill_turrets
local art_table = this.art_table
local index = art_table.index
turret.direction = 3
refill_turrets[#refill_turrets + 1] = {turret = turret, data = data.callback_data}
local artillery_data = art_table[index]
if not artillery_data then
artillery_data = {}
end
local artillery_turrets = artillery_data.artillery_turrets
if not artillery_turrets then
artillery_turrets = {}
artillery_data.artillery_turrets = artillery_turrets
local pos = turret.position
local x, y = pos.x, pos.y
artillery_data.artillery_area = {{x - 112, y}, {x + 112, y + 212}}
artillery_data.last_fire_tick = 0
art_table[#art_table + 1] = artillery_data
end
artillery_turrets[#artillery_turrets + 1] = turret
end
)
2020-05-21 23:08:23 +02:00
Public.refill_liquid_turret_callback =
Token.register(
function(turret, data)
2020-07-14 21:50:56 +02:00
local refill_turrets = this.refill_turrets
2020-05-21 23:08:23 +02:00
local callback_data = data.callback_data
callback_data.liquid = true
2020-05-23 21:18:18 +02:00
refill_turrets[#refill_turrets + 1] = {turret = turret, data = callback_data}
2020-05-21 23:08:23 +02:00
end
)
Public.power_source_callback =
Token.register(
function(turret, data)
2020-07-14 21:50:56 +02:00
local power_sources = this.power_sources
2020-11-25 20:55:51 +02:00
-- local callback_data = data.callback_data
2020-05-21 23:08:23 +02:00
2020-11-25 20:55:51 +02:00
--[[ local power_source = turret.surface.create_entity {name = 'hidden-electric-energy-interface', position = turret.position}
2020-05-21 23:08:23 +02:00
power_source.electric_buffer_size = callback_data.buffer_size
power_source.power_production = callback_data.power_production
power_source.destructible = false
local power_pole =
turret.surface.create_entity {
2020-11-23 23:10:45 +02:00
name = 'small-electric-pole',
2020-05-23 21:18:18 +02:00
position = {x = turret.position.x, y = turret.position.y}
2020-05-21 23:08:23 +02:00
}
power_pole.destructible = false
2020-11-25 20:55:51 +02:00
power_pole.disconnect_neighbour() ]]
power_sources[#power_sources + 1] = turret
2020-05-21 23:08:23 +02:00
end
)
2020-06-25 17:59:16 +02:00
Public.magic_item_crafting_callback =
Token.register(
function(entity, data)
local callback_data = data.callback_data
entity.minable = false
entity.destructible = false
entity.operable = false
local recipe = callback_data.recipe
if recipe then
entity.set_recipe(recipe)
else
local furance_item = callback_data.furance_item
if furance_item then
2020-07-25 22:22:21 +02:00
local inv = entity.get_inventory(defines.inventory.furnace_result)
2020-06-25 17:59:16 +02:00
inv.insert(furance_item)
end
end
local p = entity.position
local x, y = p.x, p.y
2020-08-09 20:22:33 +02:00
local distance = sqrt(x * x + y * y)
2020-06-25 17:59:16 +02:00
local output = callback_data.output
if #output == 0 then
add_magic_crafter_output(entity, output, distance)
else
for i = 1, #output do
local o = output[i]
add_magic_crafter_output(entity, o, distance)
end
end
if not callback_data.keep_active then
Task.set_timeout_in_ticks(2, disable_active_callback, entity) -- causes problems with refineries.
end
end
)
Public.magic_item_crafting_callback_weighted =
Token.register(
function(entity, data)
local callback_data = data.callback_data
entity.minable = false
entity.destructible = false
entity.operable = false
local weights = callback_data.weights
local loot = callback_data.loot
local p = entity.position
2020-08-09 20:22:33 +02:00
local i = random() * weights.total
2020-06-25 17:59:16 +02:00
local index = table.binary_search(weights, i)
if (index < 0) then
index = bit32.bnot(index)
end
local stack = loot[index].stack
if not stack then
return
end
local recipe = stack.recipe
if recipe then
entity.set_recipe(recipe)
else
local furance_item = stack.furance_item
if furance_item then
2020-07-30 22:27:38 +02:00
local inv = entity.get_inventory(defines.inventory.furnace_result)
2020-06-25 17:59:16 +02:00
inv.insert(furance_item)
end
end
local x, y = p.x, p.y
2020-08-09 20:22:33 +02:00
local distance = sqrt(x * x + y * y)
2020-06-25 17:59:16 +02:00
local output = stack.output
if #output == 0 then
add_magic_crafter_output(entity, output, distance)
else
for o_i = 1, #output do
local o = output[o_i]
add_magic_crafter_output(entity, o, distance)
end
end
if not callback_data.keep_active then
Task.set_timeout_in_ticks(2, disable_active_callback, entity) -- causes problems with refineries.
end
end
)
function Public.prepare_weighted_loot(loot)
local total = 0
local weights = {}
for i = 1, #loot do
local v = loot[i]
total = total + v.weight
weights[#weights + 1] = total
end
weights.total = total
return weights
end
function Public.do_random_loot(entity, weights, loot)
if not entity.valid then
return
end
entity.operable = false
--entity.destructible = false
2020-08-09 20:22:33 +02:00
local i = random() * weights.total
2020-06-25 17:59:16 +02:00
local index = table.binary_search(weights, i)
if (index < 0) then
index = bit32.bnot(index)
end
local stack = loot[index].stack
if not stack then
return
end
local df = stack.distance_factor
local count
if df then
local p = entity.position
local x, y = p.x, p.y
2020-08-09 20:22:33 +02:00
local d = sqrt(x * x + y * y)
2020-06-25 17:59:16 +02:00
count = stack.count + d * df
else
count = stack.count
end
entity.insert {name = stack.name, count = count}
end
2020-05-21 23:08:23 +02:00
Public.firearm_magazine_ammo = {name = 'firearm-magazine', count = 200}
Public.piercing_rounds_magazine_ammo = {name = 'piercing-rounds-magazine', count = 200}
Public.uranium_rounds_magazine_ammo = {name = 'uranium-rounds-magazine', count = 200}
Public.light_oil_ammo = {name = 'light-oil', amount = 100}
2020-05-23 21:18:18 +02:00
Public.artillery_shell_ammo = {name = 'artillery-shell', count = 15}
2020-05-21 23:08:23 +02:00
Public.laser_turrent_power_source = {buffer_size = 2400000, power_production = 40000}
2020-07-14 21:50:56 +02:00
function Public.reset_table()
this.power_sources = {index = 1}
this.refill_turrets = {index = 1}
this.magic_crafters = {index = 1}
this.magic_fluid_crafters = {index = 1}
end
2020-06-25 17:59:16 +02:00
Event.on_nth_tick(10, tick)
2020-11-25 20:55:51 +02:00
Event.on_nth_tick(5, do_turret_energy)
2020-06-05 18:01:32 +02:00
--Event.add(defines.events.on_tick, tick)
2020-11-25 20:55:51 +02:00
-- Event.add(defines.events.on_entity_died, turret_died)
2020-05-21 23:08:23 +02:00
return Public