189 lines
6.4 KiB
Lua
189 lines
6.4 KiB
Lua
require('scripts.prng')
|
|
require('scripts.math_utils')
|
|
|
|
--- @alias position { x?: number, y?: number }
|
|
|
|
--- @alias sprite_segment
|
|
--- | { filename?: string, width?: number, height?: number, frame_count?: number, scale?: number, shift?: position, tint?: Color }
|
|
--- | position
|
|
|
|
--- @alias sprite_segment_variants sprite_segment | sprite_segment[]
|
|
|
|
--- @alias widths { left: number, middle: number, right: number }
|
|
--- @alias heights { top: number, middle: number, bottom: number }
|
|
|
|
--- @alias sprite_definition
|
|
--- | { top_left?: sprite_segment_variants }
|
|
--- | { top?: sprite_segment_variants }
|
|
--- | { top_right?: sprite_segment_variants }
|
|
--- | { left?: sprite_segment_variants }
|
|
--- | { middle?: sprite_segment_variants }
|
|
--- | { right?: sprite_segment_variants }
|
|
--- | { bottom_left?: sprite_segment_variants }
|
|
--- | { bottom?: sprite_segment_variants }
|
|
--- | { bottom_right?: sprite_segment_variants }
|
|
--- | { top_center?: sprite_segment_variants }
|
|
--- | { left_center?: sprite_segment_variants }
|
|
--- | { center?: sprite_segment_variants }
|
|
--- | { right_center?: sprite_segment_variants }
|
|
--- | { bottom_center?: sprite_segment_variants }
|
|
--- | { filename: string, scale: number, shift: position, widths: widths, heights: heights, tint?: Color }
|
|
--- | { shadow?: boolean }
|
|
|
|
--- @alias entity_sprite
|
|
--- | { entity: sprite_definition, shadow?: sprite_definition }
|
|
|
|
--- @alias segments_data
|
|
--- | { wide_segments?: entity_sprite }
|
|
--- | { high_segments?: entity_sprite }
|
|
--- | { warehouse_segments?: entity_sprite }
|
|
--- | { trashdump_segments?: entity_sprite }
|
|
|
|
local function postprocess_sprite(sprite)
|
|
local lcm = 1
|
|
for _, layer in ipairs(sprite) do
|
|
if layer.frame_count then
|
|
lcm = math.lcm(lcm, layer.frame_count)
|
|
end
|
|
end
|
|
|
|
if lcm > 1 then
|
|
for _, layer in ipairs(sprite) do
|
|
layer.repeat_count = lcm / (layer.frame_count or 1)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- top left corner of sprite will be placed onto center of entity (plus shifts)
|
|
-- random decals may be used
|
|
-- shiftX, shiftY = local segment tile shift
|
|
-- shifts in segment(s) are pixel shifts
|
|
--- @param segments sprite_definition
|
|
--- @param segment sprite_segment_variants
|
|
--- @param shift_x number
|
|
--- @param shift_y number
|
|
--- @param width number | nil
|
|
--- @param height number | nil
|
|
--- @return table
|
|
local function create_sprite_tile(segments, segment, shift_x, shift_y, width, height)
|
|
local main_segment = segment
|
|
|
|
if segment[1] ~= nil then
|
|
if segment[2] ~= nil and prng.range(1, 100) < MergingChests.get_mod_settings().sprite_variation_chance then
|
|
main_segment = segment[1]
|
|
segment = segment[prng.range(2, table_size(segment))]
|
|
else
|
|
main_segment = segment
|
|
segment = segment[1]
|
|
end
|
|
end
|
|
|
|
width = segment.width or width
|
|
height = segment.height or height
|
|
|
|
return
|
|
{
|
|
filename = segment.filename or segments.filename,
|
|
priority = 'medium',
|
|
x = (segment.x or main_segment.x or 0),
|
|
y = (segment.y or main_segment.y or 0),
|
|
width = width,
|
|
height = height,
|
|
shift =
|
|
{
|
|
shift_x + (width / 2.0 * (segments.scale or 1) + (segment.shift and segment.shift.x or 0) + segments.shift.x) / 32.0,
|
|
shift_y + (height / 2.0 * (segments.scale or 1) + (segment.shift and segment.shift.y or 0) + segments.shift.y) / 32.0
|
|
},
|
|
scale = segment.scale or segments.scale or 1,
|
|
frame_count = segment.frame_count or 1,
|
|
draw_as_shadow = segments.shadow or false,
|
|
tint = segment.tint or segments.tint
|
|
}
|
|
end
|
|
|
|
--- @param width number
|
|
--- @param height number
|
|
--- @param segments sprite_definition
|
|
--- @param sprite_layers table
|
|
local function create_entity_sprite(width, height, segments, sprite_layers)
|
|
local x0 = -width / 2
|
|
local y0 = -height / 2
|
|
local xM = width / 2 - 1
|
|
local yM = height / 2 - 1
|
|
|
|
-- do top line
|
|
if segments.top_left then
|
|
table.insert(sprite_layers, create_sprite_tile(segments, segments.top_left, x0, y0, segments.widths.left, segments.heights.top))
|
|
end
|
|
if segments.top then
|
|
for x = 1, width - 2 do
|
|
table.insert(sprite_layers, create_sprite_tile(segments, segments.top, x0 + x, y0, segments.widths.middle, segments.heights.top))
|
|
end
|
|
end
|
|
if segments.top_right then
|
|
table.insert(sprite_layers, create_sprite_tile(segments, segments.top_right, xM, y0, segments.widths.right, segments.heights.top))
|
|
end
|
|
|
|
-- do middle horizontal lines
|
|
for y = 1, height - 2 do
|
|
if segments.left then
|
|
table.insert(sprite_layers, create_sprite_tile(segments, segments.left, x0, y0 + y, segments.widths.left, segments.heights.middle))
|
|
end
|
|
if segments.middle then
|
|
for x = 1, width - 2 do
|
|
table.insert(sprite_layers, create_sprite_tile(segments, segments.middle, x0 + x, y0 + y, segments.widths.middle, segments.heights.middle))
|
|
end
|
|
end
|
|
if segments.right then
|
|
table.insert(sprite_layers, create_sprite_tile(segments, segments.right, xM, y0 + y, segments.widths.right, segments.heights.middle))
|
|
end
|
|
end
|
|
|
|
-- do bottom line
|
|
if segments.bottom_left then
|
|
table.insert(sprite_layers, create_sprite_tile(segments, segments.bottom_left, x0, yM, segments.widths.left, segments.heights.bottom))
|
|
end
|
|
if segments.bottom then
|
|
for x = 1, width - 2 do
|
|
table.insert(sprite_layers, create_sprite_tile(segments, segments.bottom, x0 + x, yM, segments.widths.middle, segments.heights.bottom))
|
|
end
|
|
end
|
|
if segments.bottom_right then
|
|
table.insert(sprite_layers, create_sprite_tile(segments, segments.bottom_right, xM, yM, segments.widths.right, segments.heights.bottom))
|
|
end
|
|
|
|
-- centers
|
|
if segments.top_center then
|
|
table.insert(sprite_layers, create_sprite_tile(segments, segments.top_center, (x0 + xM) / 2, y0, nil, nil))
|
|
end
|
|
if segments.left_center then
|
|
table.insert(sprite_layers, create_sprite_tile(segments, segments.left_center, x0, (y0 + yM) / 2, nil, nil))
|
|
end
|
|
if segments.center then
|
|
table.insert(sprite_layers, create_sprite_tile(segments, segments.center, (x0 + xM) / 2, (y0 + yM) / 2, nil, nil))
|
|
end
|
|
if segments.right_center then
|
|
table.insert(sprite_layers, create_sprite_tile(segments, segments.right_center, xM, (y0 + yM) / 2, nil, nil))
|
|
end
|
|
if segments.bottom_center then
|
|
table.insert(sprite_layers, create_sprite_tile(segments, segments.bottom_center, (x0 + xM) / 2, yM, nil, nil))
|
|
end
|
|
end
|
|
|
|
--- @param width number
|
|
--- @param height number
|
|
--- @param segments entity_sprite
|
|
local function create_sprite(width, height, segments)
|
|
local sprite_layers = { }
|
|
|
|
create_entity_sprite(width, height, segments.entity, sprite_layers)
|
|
if segments.shadow then
|
|
create_entity_sprite(width, height, segments.shadow, sprite_layers)
|
|
end
|
|
|
|
postprocess_sprite(sprite_layers)
|
|
|
|
return sprite_layers
|
|
end
|
|
|
|
return create_sprite |