mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-02-07 13:31:40 +02:00
Merge pull request #187 from NekoBaron/patch-1
Update room_generator.lua
This commit is contained in:
commit
321a3d4c9c
@ -5,104 +5,215 @@ local table_remove = table.remove
|
||||
local math_random = math.random
|
||||
|
||||
local room_spacing = 4
|
||||
local room_spacing2 = room_spacing * 2
|
||||
|
||||
local function build_room(surface, position, vector, room_center_position, room_radius)
|
||||
local function build_room_rect(surface, position, vector, room_center_position, room_size, offset)
|
||||
local room = {}
|
||||
|
||||
local a = room_radius - 1
|
||||
--local a = room_radius - 1
|
||||
local room_area = {
|
||||
left_top = {x = room_center_position.x - a, y = room_center_position.y - a},
|
||||
right_bottom = {x = room_center_position.x + room_radius, y = room_center_position.y + room_radius}
|
||||
left_top = {x = room_center_position.x - room_size.x +1, y = room_center_position.y - room_size.y+1},
|
||||
right_bottom = {x = room_center_position.x + room_size.x, y = room_center_position.y + room_size.y}
|
||||
}
|
||||
room.room_tiles = surface.find_tiles_filtered({area = room_area})
|
||||
|
||||
room.path_tiles = {}
|
||||
for d = 1, room_spacing, 1 do
|
||||
local p = {position.x + vector[1] * d, position.y + vector[2] * d}
|
||||
local p = {position.x + vector[1] * d + offset.x, position.y + vector[2] * d + offset.y}
|
||||
local tile = surface.get_tile(p)
|
||||
table_insert(room.path_tiles, tile)
|
||||
end
|
||||
|
||||
room.entrance_tile = surface.get_tile({position.x + vector[1] * (room_spacing + 1), position.y + vector[2] * (room_spacing + 1)})
|
||||
room.entrance_tile = surface.get_tile({position.x + offset.x + vector[1] * (room_spacing + 1), position.y + offset.y + vector[2] * (room_spacing + 1)})
|
||||
|
||||
room.room_border_tiles = {}
|
||||
local left_top = {x = room_area.left_top.x - 1, y = room_area.left_top.y - 1}
|
||||
local right_bottom = {x = room_area.right_bottom.x, y = room_area.right_bottom.y}
|
||||
local t = room.room_border_tiles
|
||||
for d = 1, room_radius * 2, 1 do
|
||||
for d = 0, room_size.x * 2, 1 do
|
||||
table_insert(t, surface.get_tile({left_top.x + d, left_top.y}))
|
||||
table_insert(t, surface.get_tile({left_top.x, left_top.y + d}))
|
||||
table_insert(t, surface.get_tile({right_bottom.x - d, right_bottom.y}))
|
||||
table_insert(t, surface.get_tile({right_bottom.x, right_bottom.y - d}))
|
||||
table_insert(t, surface.get_tile({left_top.x + d, right_bottom.y}))
|
||||
end
|
||||
|
||||
for d = 1, room_size.y * 2-1, 1 do
|
||||
table_insert(t, surface.get_tile({left_top.x , left_top.y + d}))
|
||||
table_insert(t, surface.get_tile({right_bottom.x, left_top.y + d}))
|
||||
end
|
||||
table_insert(t, surface.get_tile(left_top))
|
||||
table_insert(t, surface.get_tile(right_bottom))
|
||||
table_insert(t, surface.get_tile({left_top.x + room_radius * 2, left_top.y + room_radius * 2}))
|
||||
table_insert(t, surface.get_tile({right_bottom.x - (room_radius * 2), right_bottom.y - (room_radius * 2)}))
|
||||
|
||||
room.center = room_center_position
|
||||
room.radius = room_radius
|
||||
room.radius = math.min(room_size.x,room_size.y)
|
||||
room.size = room_size
|
||||
|
||||
return room
|
||||
end
|
||||
|
||||
local function scan_direction(surface, position, vector, room_radius)
|
||||
local valid_tile_count = 0
|
||||
|
||||
for d = 1, room_radius * 2 + room_spacing * 2, 1 do
|
||||
local p = {position.x + vector[1] * d, position.y + vector[2] * d}
|
||||
local tile = surface.get_tile(p)
|
||||
if not tile.collides_with("resource-layer") then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
local a = room_radius + room_spacing + 1
|
||||
local b = room_radius + room_spacing
|
||||
|
||||
local room_center_position = {x = position.x + vector[1] * a, y = position.y + vector[2] * a}
|
||||
|
||||
local search_area = {
|
||||
{x = room_center_position.x - b, y = room_center_position.y - b},
|
||||
{x = room_center_position.x + b + 1, y = room_center_position.y + b + 1}
|
||||
}
|
||||
|
||||
|
||||
local function scan_area_empty(surface,search_area)
|
||||
local tiles = surface.find_tiles_filtered({area = search_area})
|
||||
for _, tile in pairs(tiles) do
|
||||
if not tile.collides_with("resource-layer") then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return build_room(surface, position, vector, room_center_position, room_radius)
|
||||
return true
|
||||
end
|
||||
|
||||
local function get_room_tiles(surface, position, room_radius)
|
||||
local function scan_strip_empty(surface, position, vector, length)
|
||||
for d = 0, length, 1 do
|
||||
local p = {position.x + vector[1] * d, position.y + vector[2] * d}
|
||||
local tile = surface.get_tile(p)
|
||||
if not tile.collides_with("resource-layer") then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
--Scans the X and Y independantly for best size
|
||||
local function scan_direction_full(surface, position, vector, room_max,room_min)
|
||||
local best = {x=room_min,y=room_min}
|
||||
|
||||
local a = room_min + room_spacing + 1
|
||||
local room_center_pos = {x = position.x + vector[1] * a, y = position.y + vector[2] * a}
|
||||
|
||||
local search_area = {
|
||||
{x = room_center_pos.x - best.x - room_spacing, y = room_center_pos.y - best.y - room_spacing},
|
||||
{x = room_center_pos.x + best.x + room_spacing+ 1, y = room_center_pos.y + best.y + room_spacing + 1}
|
||||
}
|
||||
|
||||
if not scan_area_empty(surface,search_area) then
|
||||
return {x=0,y=0}
|
||||
end
|
||||
|
||||
local x_end = false
|
||||
local y_end = false
|
||||
|
||||
if vector[1] == 0 then
|
||||
local yy = position.y + vector[2]
|
||||
repeat
|
||||
if not x_end then
|
||||
|
||||
if not scan_strip_empty(surface, {x = position.x + best.x + room_spacing + 1, y = yy}, vector, best.y*2 + room_spacing2) or
|
||||
not scan_strip_empty(surface, {x = position.x - best.x - room_spacing - 1, y = yy}, vector, best.y*2 + room_spacing2) then
|
||||
x_end = true
|
||||
else
|
||||
best.x = best.x + 1
|
||||
end
|
||||
if best.x >= room_max.x then x_end = true end
|
||||
end
|
||||
if not y_end then
|
||||
local xx = position.x - best.x - room_spacing - 1
|
||||
if not scan_strip_empty(surface, {x = xx, y = position.y + vector[2] * (best.y*2+room_spacing2+1)}, {1,0}, best.x*2 + room_spacing2) or
|
||||
not scan_strip_empty(surface, {x = xx, y = position.y + vector[2] * (best.y*2+room_spacing2+2)}, {1,0}, best.x*2 + room_spacing2) then
|
||||
y_end = true
|
||||
else
|
||||
best.y = best.y + 1
|
||||
end
|
||||
if best.y >= room_max.y then y_end = true end
|
||||
end
|
||||
until(x_end and y_end)
|
||||
else
|
||||
local xx = position.x + vector[1]
|
||||
repeat
|
||||
if not y_end then
|
||||
if not scan_strip_empty(surface, {x = xx, y = position.y+best.y+room_spacing+1}, vector, best.x*2 + room_spacing2) or
|
||||
not scan_strip_empty(surface, {x = xx, y = position.y-best.y-room_spacing-1}, vector, best.x*2 + room_spacing2) then
|
||||
y_end = true
|
||||
else
|
||||
best.y = best.y + 1
|
||||
end
|
||||
if best.y >= room_max.y then y_end = true end
|
||||
|
||||
end
|
||||
if not x_end then
|
||||
|
||||
local yy = position.y - best.y - room_spacing - 1
|
||||
if not scan_strip_empty(surface, {x = position.x + vector[1] * (best.x*2+room_spacing2+1), y = yy}, {0,1}, best.y*2 + room_spacing2) or
|
||||
not scan_strip_empty(surface, {x = position.x + vector[1] * (best.x*2+room_spacing2+2), y = yy}, {0,1}, best.y*2 + room_spacing2) then
|
||||
x_end = true
|
||||
else
|
||||
best.x = best.x + 1
|
||||
end
|
||||
if best.x >= room_max.x then x_end = true end
|
||||
|
||||
end
|
||||
|
||||
until(x_end and y_end)
|
||||
end
|
||||
|
||||
return best
|
||||
end
|
||||
|
||||
--get room tiles and build a room with best fit and add a chance for offset
|
||||
local function get_room_tiles_wiggle(surface, position, size, shape)
|
||||
local vectors = {{0, -1}, {0, 1}, {1, 0}, {-1, 0}}
|
||||
table_shuffle_table(vectors)
|
||||
|
||||
for _, v in pairs(vectors) do
|
||||
local room = scan_direction(surface, position, v, room_radius)
|
||||
if room then
|
||||
return room
|
||||
end
|
||||
local room_max = {x = size,y= size}
|
||||
|
||||
if shape == "wide" then
|
||||
room_max.x = room_max.x +4
|
||||
elseif shape == "tall" then
|
||||
room_max.y = room_max.y +4
|
||||
elseif shape == "big" then
|
||||
room_max.x = room_max.x +3
|
||||
room_max.y = room_max.y +3
|
||||
end
|
||||
|
||||
for _, v in pairs(vectors) do
|
||||
local room = scan_direction(surface, position, v, room_radius)
|
||||
if room then
|
||||
return room
|
||||
local full = scan_direction_full(surface, position, v, room_max,3)
|
||||
|
||||
if full.x > 0 then
|
||||
|
||||
local new_pos = position
|
||||
|
||||
local offset = {x=0,y=0}
|
||||
|
||||
if v[1] == 0 then
|
||||
if full.x > 6 then
|
||||
local max_roll = math.abs(full.x*0.5)
|
||||
if shape == "square" then max_roll = math.min(max_roll, math.abs(full.y*0.5)) end
|
||||
local roll = math_random(1 - max_roll,max_roll - 1)
|
||||
new_pos.x = new_pos.x + roll
|
||||
offset.x = -roll
|
||||
full.x = full.x - (1 + math.abs(roll * 0.5))
|
||||
|
||||
end
|
||||
else
|
||||
if full.y > 6 then
|
||||
local max_roll = math.abs(full.y*0.5)
|
||||
if shape == "square" then max_roll = math.min(max_roll, math.abs(full.x*0.5)) end
|
||||
local roll = math_random(1 - max_roll,max_roll - 1)
|
||||
new_pos.y = new_pos.y + roll
|
||||
offset.y = -roll
|
||||
full.y = full.y - (1 + math.abs(roll * 0.5))
|
||||
end
|
||||
end
|
||||
|
||||
if shape == "square" then
|
||||
--game.print("forcing square")
|
||||
if full.x > full.y then
|
||||
full.x = full.y
|
||||
else
|
||||
full.y = full.x
|
||||
end
|
||||
end
|
||||
|
||||
local room_center_position = {x = new_pos.x + v[1] * (full.x + room_spacing + 1), y = new_pos.y + v[2] * (full.y + room_spacing + 1)}
|
||||
return build_room_rect(surface, new_pos, v, room_center_position, full, offset)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local function expand_path_tiles_width(surface, room)
|
||||
if not room then return end
|
||||
|
||||
local max_expansion_count = 0
|
||||
if math_random(1, 3) == 1 then max_expansion_count = 1 end
|
||||
if math_random(1, 9) == 1 then max_expansion_count = 2 end
|
||||
if max_expansion_count == 0 then return end
|
||||
local max_expansion_count = 1
|
||||
if math_random(1, 4) == 1 then max_expansion_count = 2 end
|
||||
if math_random(1, 16) == 1 then max_expansion_count = 3 end
|
||||
--if max_expansion_count == 0 then return end
|
||||
|
||||
local path_tiles = room.path_tiles
|
||||
local vectors = {{0, -1}, {0, 1}, {1, 0}, {-1, 0}}
|
||||
@ -218,32 +329,32 @@ local function build_bridge(surface, position)
|
||||
|
||||
end
|
||||
|
||||
function Public.get_room(surface, position)
|
||||
local room_sizes = {}
|
||||
for i = 1, 14, 1 do
|
||||
room_sizes[i] = i + 1
|
||||
function Public.get_room(surface, position, shape)
|
||||
if not shape then
|
||||
shape = "square"
|
||||
end
|
||||
table_shuffle_table(room_sizes)
|
||||
|
||||
local last_size = room_sizes[1]
|
||||
for i = 1, #room_sizes, 1 do
|
||||
if room_sizes[i] <= last_size then
|
||||
last_size = room_sizes[i]
|
||||
local room = get_room_tiles(surface, position, last_size)
|
||||
expand_path_tiles_width(surface, room)
|
||||
if room then
|
||||
return room
|
||||
end
|
||||
end
|
||||
|
||||
local room_max = math_random(3,14)
|
||||
local room = get_room_tiles_wiggle(surface, position, room_max, shape)
|
||||
|
||||
if room then
|
||||
expand_path_tiles_width(surface, room)
|
||||
return room
|
||||
end
|
||||
|
||||
|
||||
local room = build_bridge(surface, position)
|
||||
expand_path_tiles_width(surface, room)
|
||||
if room then return room end
|
||||
if room then
|
||||
expand_path_tiles_width(surface, room)
|
||||
return room
|
||||
end
|
||||
end
|
||||
|
||||
function Public.draw_random_room(surface, position)
|
||||
local room = Public.get_room(surface, position)
|
||||
function Public.draw_random_room(surface, position,shape)
|
||||
if not shape then
|
||||
shape = "square"
|
||||
end
|
||||
|
||||
local room = Public.get_room(surface, position,shape)
|
||||
if not room then return end
|
||||
|
||||
for _, tile in pairs(room.path_tiles) do
|
||||
@ -262,4 +373,4 @@ function Public.draw_random_room(surface, position)
|
||||
end
|
||||
end
|
||||
|
||||
return Public
|
||||
return Public
|
||||
|
Loading…
x
Reference in New Issue
Block a user