305 lines
10 KiB
Lua

local create_sprite = require('scripts.sprite_generation')
--- @param chest_name string
--- @param width number
--- @param height number
local function get_circuit_connector(chest_name, width, height)
local mod_settings = MergingChests.get_mod_settings(chest_name)
local variation, x, y
local _, _, side, position = string.find(mod_settings.circuit_connector_position, '([^-]+)[-]([^-]+)')
if side == 'right' then
variation = 24
x = -width / 2
elseif side == 'left' then
variation = 28
x = width / 2
elseif side == 'bottom' then
variation = 26
y = height / 2 - 0.5
elseif side == 'center' then
if width >= height then
variation = 26
x = 0
y = height / 2 - 0.5
else
variation = 24
x = -width / 2
y = 0
end
end
if position == 'top' then
y = -height / 2 + 0.5
elseif position == 'middle' then
if x == nil then
x = 0
else
y = 0
end
elseif position == 'bottom' then
y = height / 2 - 0.75
elseif position == 'right' then
x = -width / 2 + 0.5
elseif position == 'left' then
x = width / 2 - 0.5
end
return circuit_connector_definitions.create(
universal_connector_template,
{
{
variation = variation,
main_offset = { x, y },
shadow_offset = { x + 0.1, y + 0.1 },
show_shadow = false
}
}
)
end
--- @alias entity_data
--- | { chest_name: string, override_prototype_properties?: table }
--- @param entity_data entity_data
--- @param loc_name table
--- @param subgroup string
--- @param width number
--- @param height number
--- @param segment_data entity_sprite
local function create_entity(entity_data, loc_name, subgroup, width, height, segment_data)
local base_chest = data.raw['logistic-container'][entity_data.chest_name] or data.raw.container[entity_data.chest_name]
if base_chest == nil then
error('Chest with name '..entity_data.chest_name..' not found')
end
local sprite = create_sprite(width, height, segment_data)
local connector = get_circuit_connector(entity_data.chest_name, width, height)
local type_specific_properties
if base_chest.logistic_mode then
type_specific_properties = {
type = 'logistic-container',
logistic_mode = base_chest.logistic_mode,
animation_sound = base_chest.animation_sound,
opened_duration = 7,
animation = {
layers = sprite
}
}
if base_chest.logistic_mode == 'storage' then
type_specific_properties.max_logistic_slots = 1
end
else
type_specific_properties = {
type = 'container',
picture = {
layers = sprite
}
}
end
local merged_chest_name = MergingChests.get_merged_chest_name(entity_data.chest_name, width, height)
table.insert(data.raw['selection-tool'][MergingChests.merge_selection_tool_name].alt_entity_filters, merged_chest_name)
return util.merge({
type_specific_properties,
{
name = merged_chest_name,
localised_name = loc_name,
icon = base_chest.icon,
icons = base_chest.icons,
icon_size = base_chest.icon_size,
fast_replaceable_group = 'merged-container',
open_sound = base_chest.open_sound,
close_sound = base_chest.close_sound,
max_health = base_chest.max_health * math.min(width * height, 10),
inventory_size = MergingChests.get_inventory_size(base_chest.inventory_size, width * height, entity_data.chest_name),
flags = { 'placeable-player', 'player-creation' },
minable = { mining_time = 2, result = entity_data.chest_name, count = width * height },
placeable_by = { item = entity_data.chest_name, count = width * height },
corpse = 'medium-remnants',
dying_explosion = 'medium-explosion',
vehicle_impact_sound = { filename = '__base__/sound/car-metal-impact.ogg', volume = 0.65 },
collision_box = { { -width / 2 + 0.15, -height / 2 + 0.15 }, { width / 2 - 0.15, height / 2 - 0.15 } },
selection_box = { { -width / 2, -height / 2 }, { width / 2, height / 2 } },
subgroup = subgroup,
circuit_wire_connection_point = connector.points,
circuit_connector_sprites = connector.sprites,
circuit_wire_max_distance = default_circuit_wire_max_distance + math.min(width, height) - 1,
},
entity_data.override_prototype_properties or {}
})
end
--- @param entity_data entity_data
--- @param segment_data entity_sprite
--- @param width number
local function create_wide_chest_entity(entity_data, segment_data, width)
return create_entity(
entity_data,
{ 'chest-name.'..MergingChests.prefix_with_modname('wide-'..entity_data.chest_name), width },
MergingChests.item_group_names.wide_chests,
width,
1,
segment_data
)
end
--- @param entity_data entity_data
--- @param segment_data entity_sprite
--- @param height number
local function create_high_chest_entity(entity_data, segment_data, height)
return create_entity(
entity_data,
{ 'chest-name.'..MergingChests.prefix_with_modname('high-'..entity_data.chest_name), height },
MergingChests.item_group_names.high_chests,
1,
height,
segment_data
)
end
--- @param entity_data entity_data
--- @param segment_data entity_sprite
--- @param width number
--- @param height number
local function create_warehouse_entity(entity_data, segment_data, width, height)
return create_entity(
entity_data,
{ 'chest-name.'..MergingChests.prefix_with_modname(entity_data.chest_name..'-warehouse'), width, height },
MergingChests.item_group_names.warehouses,
width,
height,
segment_data
)
end
--- @param entity_data entity_data
--- @param segment_data entity_sprite
--- @param width number
--- @param height number
local function create_trashdump_entity(entity_data, segment_data, width, height)
return create_entity(
entity_data,
{ 'chest-name.'..MergingChests.prefix_with_modname(entity_data.chest_name..'-trashdump'), width, height },
MergingChests.item_group_names.trashdumps,
width,
height,
segment_data
)
end
--- @type { [setting_allowed_value]: boolean[] }
local setting_value_to_enabled_flags = {
['none'] = { false, false, false },
['chest'] = { true, false, false },
['warehouse'] = { false, true, false },
['trashdump'] = { false, false, true },
['chest-warehouse'] = { true, true, false },
['chest-trashdump'] = { true, false, true },
['warehouse-trashdump'] = { false, true, true },
['chest-warehouse-trashdump'] = { true, true, true }
}
--- Creates merged chest prototypes
---
--- Reads settings made during settings stage with same `chest_name`.
--- @param entity_data entity_data
--- @param segments_data segments_data
function MergingChests.create_mergeable_chest(entity_data, segments_data)
local setting = settings.startup[MergingChests.chest_specific_setting_name(MergingChests.setting_names.mergeable_chest, entity_data.chest_name)]
local enable_chest, enable_warehouse, enable_trashdump = table.unpack(
setting_value_to_enabled_flags[setting and setting.value or 'none']
)
if setting and MergingChests.is_mod_active(MergingChests.all_types_mod_name) then
enable_chest = true
enable_warehouse = true
enable_trashdump = true
end
local mod_settings = MergingChests.get_mod_settings(entity_data.chest_name)
local max_area = 0
if enable_chest and segments_data.high_segments then
for height = 2, math.min(mod_settings.max_height, mod_settings.max_area) do
if MergingChests.is_size_allowed(1, height, entity_data.chest_name) then
data:extend({ create_high_chest_entity(entity_data, segments_data.high_segments, height) })
max_area = math.max(max_area, height)
end
end
end
for width = 2, math.min(mod_settings.max_width, mod_settings.max_area) do
if enable_chest and segments_data.wide_segments then
if MergingChests.is_size_allowed(width, 1, entity_data.chest_name) then
data:extend({ create_wide_chest_entity(entity_data, segments_data.wide_segments, width) })
max_area = math.max(max_area, width)
end
end
for height = 2, math.min(mod_settings.max_height, mod_settings.max_area) do
if MergingChests.is_size_allowed(width, height, entity_data.chest_name) then
if enable_trashdump and width > mod_settings.warehouse_threshold and height > mod_settings.warehouse_threshold and segments_data.trashdump_segments then
data:extend({ create_trashdump_entity(entity_data, segments_data.trashdump_segments, width, height) })
max_area = math.max(max_area, width * height)
elseif enable_warehouse and segments_data.warehouse_segments then
data:extend({ create_warehouse_entity(entity_data, segments_data.warehouse_segments, width, height) })
max_area = math.max(max_area, width * height)
end
end
end
end
if enable_chest or enable_warehouse or enable_trashdump then
table.insert(data.raw['selection-tool'][MergingChests.merge_selection_tool_name].entity_filters, entity_data.chest_name)
data.raw.item[entity_data.chest_name].stack_size = math.max(data.raw.item[entity_data.chest_name].stack_size, max_area)
end
end
--- Sets next_upgrade of chests of type `type` merged from `chest_name`
--- @param type `logistic-container` | `container`
--- @param chest_name string
--- @param next_upgrade string
function MergingChests.set_next_upgrade_of(type, chest_name, next_upgrade)
for _, prototype in pairs(data.raw[type]) do
local name, width, height = MergingChests.get_merged_chest_info(prototype.name)
if name == chest_name and width and height then
local merged_upgrade_name = MergingChests.get_merged_chest_name(next_upgrade, width, height)
if data.raw[type][merged_upgrade_name] then
prototype.next_upgrade = merged_upgrade_name
end
end
end
end
--- Disables next_upgrade of chests of type `type` merged from `chest_name`
--- @param type `logistic-container` | `container`
--- @param chest_name string
function MergingChests.disable_next_upgrade_of(type, chest_name)
for _, prototype in pairs(data.raw[type]) do
local name, _ = MergingChests.get_merged_chest_info(prototype.name)
if name == chest_name then
prototype.next_upgrade = nil
end
end
end
--- Disables next_upgrade of chests which of type `type` which are upgraded to `chest_name`
--- @param type `logistic-container` | `container`
--- @param chest_name string
function MergingChests.disable_next_upgrade_to(type, chest_name)
for _, prototype in pairs(data.raw[type]) do
if prototype.next_upgrade then
local name, _ = MergingChests.get_merged_chest_info(prototype.next_upgrade)
if name == chest_name then
prototype.next_upgrade = nil
end
end
end
end