Ensured random dungeons place large events properly

This commit is contained in:
Maruno17
2023-06-20 19:26:40 +01:00
parent 17e8be9dca
commit 4fc0806c8a

View File

@@ -376,6 +376,7 @@ module RandomDungeon
@usable_width -= 1 if @usable_width.odd? @usable_width -= 1 if @usable_width.odd?
@usable_height -= 1 if @usable_height.odd? @usable_height -= 1 if @usable_height.odd?
end end
@room_rects = []
@map_data = DungeonLayout.new(@width, @height) @map_data = DungeonLayout.new(@width, @height)
@need_redraw = false @need_redraw = false
end end
@@ -804,6 +805,7 @@ module RandomDungeon
end end
x = x.clamp(@buffer_x, @usable_width - @buffer_x - width) x = x.clamp(@buffer_x, @usable_width - @buffer_x - width)
y = y.clamp(@buffer_y, @usable_height - @buffer_y - height) y = y.clamp(@buffer_y, @usable_height - @buffer_y - height)
@room_rects.push([x, y, width, height])
paint_ground_rect(x, y, width, height, :room) paint_ground_rect(x, y, width, height, :room)
end end
@@ -1002,19 +1004,36 @@ module RandomDungeon
end end
end end
# Returns a random room tile in the dungeon that isn't too close to a # Returns a random room tile a random room where an event of the given size
# corridor (to avoid blocking a room's entrance). # can be placed. Events cannot be placed adjacent to or overlapping each
def get_random_room_tile(occupied_tiles) # other, and can't be placed right next to the wall of a room (to prevent
ar1 = AntiRandom.new(@width) # them blocking a corridor).
ar2 = AntiRandom.new(@height) def get_random_room_tile(occupied_tiles, event_width = 1, event_height = 1)
((occupied_tiles.length + 1) * 1000).times do valid_rooms = @room_rects.clone
x = ar1.get valid_rooms.delete_if { |rect| rect[2] <= event_width + 1 || rect[3] <= event_height + 1 }
y = ar2.get return nil if valid_rooms.empty?
next if !isRoom?(x, y) 1000.times do
next if occupied_tiles.any? { |item| (item[0] - x).abs < 2 && (item[1] - y).abs < 2 } room = valid_rooms.sample
ret = [x, y] x = 1 + rand(room[2] - event_width - 1)
occupied_tiles.push(ret) y = 1 + rand(room[3] - event_height - 1)
return ret valid_placement = true
event_width.times do |i|
event_height.times do |j|
if occupied_tiles.any? { |item| (item[0] - (room[0] + x + i)).abs < 2 && (item[1] - (room[1] + y + j)).abs < 2 }
valid_placement = false
end
break if !valid_placement
end
break if !valid_placement
end
next if !valid_placement
# Found valid placement; use it
event_width.times do |i|
event_height.times do |j|
occupied_tiles.push([room[0] + x + i, room[1] + y + j])
end
end
return [room[0] + x, room[1] + y + event_height - 1]
end end
return nil return nil
end end
@@ -1055,20 +1074,34 @@ EventHandlers.add(:on_game_map_setup, :random_dungeon,
map.height = dungeon.height map.height = dungeon.height
map.data.resize(map.width, map.height, 3) map.data.resize(map.width, map.height, 3)
dungeon.generateMapInPlace(map) dungeon.generateMapInPlace(map)
occupied_tiles = [] failed = false
# Reposition the player 100.times do |i|
tile = dungeon.get_random_room_tile(occupied_tiles) failed = false
if tile occupied_tiles = []
$game_temp.player_new_x = tile[0] # Reposition events
$game_temp.player_new_y = tile[1] map.events.each_value do |event|
end event_width = 1
# Reposition events event_height = 1
map.events.each_value do |event| if event.name[/size\((\d+),(\d+)\)/i]
tile = dungeon.get_random_room_tile(occupied_tiles) event_width = $~[1].to_i
if tile event_height = $~[2].to_i
end
tile = dungeon.get_random_room_tile(occupied_tiles, event_width, event_height)
failed = true if !tile
break if failed
event.x = tile[0] event.x = tile[0]
event.y = tile[1] event.y = tile[1]
end end
next if failed
# Reposition the player
tile = dungeon.get_random_room_tile(occupied_tiles)
next if !tile
$game_temp.player_new_x = tile[0]
$game_temp.player_new_y = tile[1]
break
end
if failed
raise _INTL("Couldn't place all events and the player in rooms.")
end end
} }
) )