Files
SpaceBots/Maps/MapGenerator/levelGenerator.gd

721 lines
26 KiB
GDScript3
Raw Permalink Normal View History

2026-01-21 23:40:20 +01:00
extends Node3D
class_name LevelGenerator
var levelGrid: Array[Array]
@export var gridSizeX: int = 15
@export var gridSizeY: int = 3
@export var gridSizeZ: int = 15
@export var bufferSize: int = 5
@export var shipLogic: ShipLogic
@export var doorBlock: PackedScene # Temporary
@export var doorOBJ: PackedScene #Temporary
@export var tile: PackedScene # Temporary
@export var lamp: PackedScene # Temporary
@export var tileWall: PackedScene # Temporary
@export var tileCorner: PackedScene # Temporary
var levelGenSeed: int = 0
var globalParameters: ParamterList
var rng: RandomNumberGenerator = RandomNumberGenerator.new() #Get random values, usefull for random level generation huh
var currentMission: Mission
var doorSpawnPoints: Array[DoorPosition] #Where to put them doors
var doorBlockSpawnPoints: Array[DoorPosition] #Where to put them door blockers
var biomeExitPositions: Array[BiomeExit] #Points where you can leave a biome
var biomeExitChecker: RoomData = RoomData.new(preload("res://Maps/MapGenerator/BiomeExitChecker.png").get_image(),"") #Nonexisten Room used to check if a door is a valid Biome Exit
var connectPathPositions: PackedVector2Array #Where to place floor tiles of connecting paths
var astar: AStar2D = AStar2D.new()
func generate(usingSeed: int) -> void:
levelGenSeed = usingSeed
initRandom() # Set seed for level generation
initGrid() #Assign a new grid space object to each space of the 5x5x5m grid
##Center the world
position.x = -gridSizeX*2.5
position.z = -gridSizeZ*2.5
for x in gridSizeX:
for y in gridSizeY:
for z in gridSizeZ:
debugCubeAtPos(levelGrid[x][y][z].position*5)
func initRandom() -> void:
rng.set_seed(hash(levelGenSeed))
func initGrid() -> void:
for x in gridSizeX:
var newRow: Array
levelGrid.push_back(newRow)
for y in gridSizeY:
var newCol: Array
levelGrid[x].push_back(newCol)
for z in gridSizeZ:
var newCell := GridCell.new()
newCell.position = Vector3i(x,y,z)
levelGrid[x][y].push_back(newCell)
func debugCubeAtPos(pos: Vector3):
var debugCube: PackedScene = preload("res://Maps/Rooms/Generator/4Way/4WayRoomGenerator.tscn")
addObject(debugCube,self,pos+Vector3(2.5,0,2.5))
func addObject(AddedObject:PackedScene, Parent: Node3D, Position: Vector3, Rotation: Vector3= Vector3(0,0,0)) -> Node:
if !AddedObject:
print("tried to add object but packed scene is null")
return
var obj = AddedObject.instantiate()
Parent.add_child(obj)
obj.position = Position
obj.rotation = Rotation
return obj
## OLD LEVEL GEN CODE
#func generate(usingSeed: int) -> void:
#levelGenSeed = usingSeed
#
#initRandom() # Set seed for level generation
#initGrid() #Assign a new grid space object to each space of the 1x1m grid
#
##Center the world
#position.x = -gridSize/2
#position.z = -gridSize/2
#
#currentMission = RescueMission.new() #Have something choose the mission type in this part later
#
##Biomes
#generateBufferBiome(bufferSize)
#var doorList: Array[DoorPosition] #Seccond Array contains door positions
#for bPrio in currentMission.biomes.size():
#doorList = placeBiomes(currentMission.biomes[bPrio])
#spreadBiomes()
#
##Rooms into Biomes
#placeRooms(doorList)
#
##Doors
##chooseBiomeExits()
#doorsAtBiomeExits()
#findValidDoors()
#spawnDoors()
#
##Generate Astar setup for finding Paths between Biomes and Rooms
#generateAstarPoints()
#connectAstarPoints()
#weightAstarPoints()
#
##Connect Biomes
#connectPathPositions = generateConnectionPath()
#generateFloorPositions()
#placeFloorPositionTiles()
#placeWallsAlongTiles()
#
#
#
#
#
#shipLogic.onLevelGenFinished()
#shipLogic.main.mapScreen.generateMap(levelGrid)
#
##Misc Utility
#func abandonSeed() -> void:
#print("SEED IS NOT VALID")
#
#func initRandom() -> void:
#rng.set_seed(hash(levelGenSeed))
#
#func initGrid() -> void:
#for x in gridSizeX:
#var newRow: Array
#levelGrid.push_back(newRow)
#for y in gridSizeY:
#var newCol: Array
#levelGrid[x].push_back(newCol)
#for z in gridSizeZ:
#var newCell := GridCell.new()
#newCell.position = Vector3i(x,y,z)
#levelGrid[x].push_back(newCell)
#
#func addGridCells(cell1: GridCell,cell2: GridCell) -> GridCell:
#var returnCell: GridCell = GridCell.new()
#returnCell.spaceTaken = cell1.spaceTaken or cell2.spaceTaken
#returnCell.door = cell1.door or cell2.door
#if cell1.door and !cell2.door:
#returnCell.doorOrientation = cell1.doorOrientation
#else:
#returnCell.doorOrientation = cell2.doorOrientation
#returnCell.position = cell1.position
#returnCell.biome = cell1.biome
#returnCell.biomeConnection = cell1.biomeConnection
#return returnCell
#
#func shuffleArray(array: Array) -> Array:
#for i in array.size()-1:
##Get Array indexes
#var iA: int = array.size()-1-i
#var iB: int = rng.randi_range(0,array.size()-2-i)
#
##Get two elements from the array
#var a = array[iA]
#var b = array[iB]
#
##Swap both elements
#array[iB] = a
#array[iA] = b
#
#return array
#
#func addArrays2D(array1: Array[Array], array2: Array[Array], arr2pos: Vector2i = Vector2i(0,0)) -> void:
#if array1.size() <= (arr2pos.x) + array2.size(): return
#if array1[arr2pos.y].size() <= (arr2pos.y) + array2[0].size(): return
#for x in array2.size():
#for y in array2[x].size():
#array1[x+arr2pos.x][y+arr2pos.y] = addGridCells(array1[x+arr2pos.x][y+arr2pos.y],array2[x][y])
#
#func checkOverlapArrays2D(array1: Array[Array], array2: Array[Array], arr2pos: Vector2i = Vector2i(0,0)) -> bool:
#if array1.size() <= arr2pos.x + array2.size() or arr2pos.x < 0: return true
#if array1[arr2pos.y].size() <= arr2pos.y + array2[0].size() or arr2pos.y < 0: return true
#for x in array2.size():
#for y in array2[x].size():
#if array1[x+arr2pos.x][y+arr2pos.y].spaceTaken and array2[x][y].spaceTaken: return true
#return false
#
#func checkBiomeOverlap(biome: String, pos: Vector2i, length: int, height: int) -> bool:
#if levelGrid.size() <= pos.x + length or pos.x < 0: return true
#if levelGrid[pos.y].size() <= pos.y + height or pos.y < 0: return true
#for x in length:
#for y in height:
#if levelGrid[x+pos.x][y+pos.y].biome: return true
#return false
#
#func rotateArray2D(array: Array[Array], numberOfRotationsBy90Degrees: int) -> void:
#var size: int = array.size()
#var layerCount: int = size/2
#
#for x in numberOfRotationsBy90Degrees%4:
#for layer in layerCount:
#var first: int = layer
#var last: int = size - first - 1
#
#for element in range(first, last):
#var offset = element - first
#
#var top = array[first][element]
#var right = array[element][last]
#var bot = array[last][last-offset]
#var left = array[last-offset][first]
#
#array[element][last] = top
#array[last][last-offset] = right
#array[last-offset][first] = bot
#array[first][element] = left
#
#func getDoorPosition(cell: GridCell, GridCellPosition: Vector2i) -> DoorPosition:
#if !cell.door:
#print("Tried to get door at cell that isnt a door")
#return null
#var returnDoorPosition := DoorPosition.new()
#returnDoorPosition.pos = GridCellPosition
#returnDoorPosition.orientation = cell.doorOrientation
#return returnDoorPosition
#
#func addObject(AddedObject:PackedScene, Parent: Node3D, Position: Vector3, Rotation: Vector3= Vector3(0,0,0)) -> Node:
#if !AddedObject:
#print("tried to add object but packed scene is null")
#return
#var obj = AddedObject.instantiate()
#Parent.add_child(obj)
#obj.position = Position
#obj.rotation = Rotation
#return obj
#
#func changeBiomeArea2D(biome: String,pos:Vector2i,length: int,height: int):
#for x in length:
#for y in height:
#levelGrid[pos.x+x][pos.y+y].biome = biome
#
##Spawning Rooms
#func rotateRoomData(roomData: RoomData, numberOfRotationsBy90Degrees: int) -> void:
#rotateArray2D(roomData.roomGrid,numberOfRotationsBy90Degrees)
#roomData.rotations = wrapi(roomData.rotations + numberOfRotationsBy90Degrees,0,4)
#for door in roomData.doorPositions:
#door.rotatePosRight(roomData.roomGrid.size(),numberOfRotationsBy90Degrees)
#roomData.roomGrid[door.pos.x][door.pos.y].doorOrientation = wrapi(door.orientation-2,0,4)
#
#func spawnRoom(roomDataInput: RoomData,pos: Vector2i,numberOfRotationsBy90Degrees: int = 0, centered: bool = false) -> Array[DoorPosition]: #Pos corresponds to the upper left corner of the room immage
#var roomData: RoomData = roomDataInput.duplicateRoom()
#var roomScene: PackedScene = roomDataInput.roomScene
#rotateRoomData(roomData,numberOfRotationsBy90Degrees)
#var roomGrid := roomData.roomGrid
#var doorPositions: Array[DoorPosition] = roomData.doorPositions
#if centered:
#pos = Vector2i(pos.x-(roomGrid.size()/2),pos.y-(roomGrid[0].size()/2))
#
#addArrays2D(levelGrid,roomGrid,pos)
#
##Make Room
#var room: BasicRoom = addObject(roomScene,self,Vector3(pos.x+(roomGrid.size()/2),0,pos.y+(roomGrid[0].size()/2)),Vector3(0,(roomData.rotations%4)*PI/2,0))
#room.biomeName = levelGrid[pos.x][pos.y].biome
#shipLogic.addRoomToRoomList(room)
#
#
#
#for door in doorPositions:
#door.pos = pos + door.pos
#
#
#
#return doorPositions
#
#func getDoorFromRoom(roomData: RoomData,index: int) -> DoorPosition:
#return roomData.doorPositions[index % roomData.doorPositions.size()]
#
#func putRoomAtDoor(roomData: RoomData, door: DoorPosition,spawnDoorIndex: int) -> Array: ##Return array contains roomData, spawn Pos in that order
##Init Values:
#var spawnDoor: DoorPosition = getDoorFromRoom(roomData,spawnDoorIndex) #Which door from the spawned room connects to the exiting room
#var doorOrientationDifference : int = wrapi(spawnDoor.orientation - door.orientation,0,4) #Difference in orinet. between spawned and existing room
#var numberOfRoomRotations: int = 0 #How many rotations are needed to make spawned rooms spawn door face the existing door
#var spawnPos: Vector2i
#var doorOffset: Vector2i #Offset by 1 space so the doors are next to eachother and not inside eachoter
#
##Find number of rotations and then rotate the room
#if !doorOrientationDifference == 2:
#if doorOrientationDifference == 1:
#numberOfRoomRotations = 3
#if doorOrientationDifference == 0:
#numberOfRoomRotations = 2
#if doorOrientationDifference == 3:
#numberOfRoomRotations = 1
#rotateRoomData(roomData,numberOfRoomRotations)
#
##Get new values for spawnDoor and set door offset
#spawnDoor = getDoorFromRoom(roomData,spawnDoorIndex)
#match spawnDoor.orientation:
#0: doorOffset = Vector2i(0,-1)
#1: doorOffset = Vector2i(1,0)
#2: doorOffset = Vector2i(0,1)
#3: doorOffset = Vector2i(-1,0)
#
##Set spawn pos and return values
#spawnPos = door.pos - spawnDoor.pos + doorOffset
#var returnArray: Array = [roomData,spawnPos]
#return returnArray
#
#func spawnRoomAtDoor(roomDataInput: Array[RoomData], door: DoorPosition, biome: String) -> Array[DoorPosition]:
#var returnArray: Array[DoorPosition]
#var roomData: RoomData = null
#var spawnDoorIndex: int = -1
##Choose the room to use
#var rooms: Array[RoomData] = roomDataInput.duplicate()
#
#shuffleArray(rooms)
#for r in floor(rooms.size()/2):
##Randomise door checking order
#var doorIndices: Array[int]
#for x in rooms[r].doorPositions.size():
#doorIndices.push_back(x)
#shuffleArray(doorIndices)
#
##Check if doorIndex fits and assign roomData and spawnDoorIndex if it does
#for doorIndex in doorIndices:
#if checkIfRoomFits(rooms[r],door,doorIndex, biome):
#roomData = rooms[r].duplicateRoom()
#spawnDoorIndex = doorIndex
#break
#
##Check if a room has been found
#if !roomData or spawnDoorIndex == -1:
#var checkPosition = door.pos
#match door.orientation:
#0: checkPosition += Vector2i(-1,-2)
#1: checkPosition += Vector2i(0,-1)
#2: checkPosition += Vector2i(-1,0)
#3: checkPosition += Vector2i(-2,-1)
#if !checkOverlapArrays2D(levelGrid,biomeExitChecker.roomGrid,checkPosition):
#biomeExitPositions.push_back(BiomeExit.new(door.pos,door.orientation,biome))
#return returnArray
#
##Get Spawn Info and spawn room
#var spawnInfo: Array = putRoomAtDoor(roomData,door,spawnDoorIndex)
#spawnRoom(spawnInfo[0],spawnInfo[1])
#returnArray = spawnInfo[0].doorPositions
#for x in returnArray.size():
#returnArray[x].pos = spawnInfo[1] + returnArray[x].pos
#return returnArray
#
#func checkIfBiomeFits(length: int, height: int, pos: Vector2i, biome: String) -> bool:
#if levelGrid.size() <= pos.x + length or pos.x < 0: return true
#if levelGrid[pos.y].size() <= pos.y + height or pos.y < 0: return true
#for x in length:
#for y in height:
#if levelGrid[x+pos.x][y+pos.y].biome != biome:
#return false
#return true
#
#func checkIfRoomFits(roomDataInput: RoomData,door: DoorPosition,spawnDoorIndex: int, biome: String) -> bool:
#var roomData: RoomData = roomDataInput.duplicateRoom()
#var spawnInfo: Array = putRoomAtDoor(roomData,door,spawnDoorIndex)
#
#if !checkOverlapArrays2D(levelGrid,spawnInfo[0].roomGrid,spawnInfo[1]) and checkIfBiomeFits(spawnInfo[0].roomGrid.size(),spawnInfo[0].roomGrid[0].size(),spawnInfo[1],biome):
#return true
#else:
#return false
#
#func isOutOfArray2DBounds(sizeX: int, sizeY: int, pos: Vector2i) -> bool:
#if pos.x >= sizeX or pos.x < 0 or pos.y >= sizeY or pos.y < 0:
#return true
#else:
#return false
#
#func isValidDoor(pos:Vector2i) -> bool: # Checks if the door connects to another door using its orientation,
##if this function finds a valid door, it removes the door status from the other door to avoid duplicated doors
#match levelGrid[pos.x][pos.y].doorOrientation:
#0:
#if isOutOfArray2DBounds(levelGrid.size(),levelGrid[0].size(),Vector2i(pos.x,pos.y-1)): return false
#if !levelGrid[pos.x][pos.y-1].door: return false
#else: levelGrid[pos.x][pos.y-1].door = false
#1:
#if isOutOfArray2DBounds(levelGrid.size(),levelGrid[0].size(),Vector2i(pos.x+1,pos.y)): return false
#if !levelGrid[pos.x+1][pos.y].door: return false
#else: levelGrid[pos.x+1][pos.y].door = false
#2:
#if isOutOfArray2DBounds(levelGrid.size(),levelGrid[0].size(),Vector2i(pos.x,pos.y+1)): return false
#if !levelGrid[pos.x][pos.y+1].door: return false
#else: levelGrid[pos.x][pos.y+1].door = false
#3:
#if isOutOfArray2DBounds(levelGrid.size(),levelGrid[0].size(),Vector2i(pos.x-1,pos.y)): return false
#if !levelGrid[pos.x-1][pos.y].door: return false
#else: levelGrid[pos.x-1][pos.y].door = false
#return true
#
#func findValidDoors() -> void:
#for x in levelGrid.size():
#for y in levelGrid[x].size():
#if levelGrid[x][y].door:
#var newDoorObject := DoorPosition.new()
#newDoorObject.pos = Vector2i(x,y)
#newDoorObject.orientation = levelGrid[x][y].doorOrientation
#if isValidDoor(Vector2i(x,y)):
#doorSpawnPoints.push_back(newDoorObject)
#else:
#doorBlockSpawnPoints.push_back(newDoorObject)
#
#func spawnDoors() -> void:
#for doorSpawn in doorSpawnPoints:
#addObject(doorOBJ,self,Vector3(doorSpawn.pos.x+0.5,0,doorSpawn.pos.y+0.5),Vector3(0,doorSpawn.orientation*-PI/2,0))
##debugCubeAtPos(doorSpawn.pos)
#for doorBlockSpawn in doorBlockSpawnPoints:
#addObject(doorBlock,self,Vector3(doorBlockSpawn.pos.x+0.5,0,doorBlockSpawn.pos.y+0.5),Vector3(0,doorBlockSpawn.orientation*-PI/2,0))
#
#func placeRooms(doorList: Array[DoorPosition]) -> void:
#var nextDoors: Array[DoorPosition] = []
#
##YES I KNOW A DO WHILE LOOP IS BETTER HERE BUT GODOT DOESNT HAVE IT
#for door in doorList:
#var doorBiome: Biome = getBiome(levelGrid[door.pos.x][door.pos.y].biome)
#nextDoors += spawnRoomAtDoor(doorBiome.roomList.rooms,door,doorBiome.name)
#doorList = nextDoors
#nextDoors = []
#
#while !doorList.is_empty():
#for door in doorList:
#var doorBiome: Biome = getBiome(levelGrid[door.pos.x][door.pos.y].biome)
#nextDoors += spawnRoomAtDoor(doorBiome.roomList.rooms,door,doorBiome.name)
#doorList = nextDoors
#nextDoors = []
#
##Generating Biomes
#func generateBufferBiome(bufferWidth: int) -> void:
#for x in levelGrid.size():
#for y in levelGrid[x].size():
#if (x < bufferWidth) or (y < bufferWidth) or (x > levelGrid.size() - bufferWidth) or (y > levelGrid.size() - bufferWidth):
#levelGrid[x][y].biome = "buffer"
#
#
#func getBiome(biomeName: String) -> Biome:
#for prio in currentMission.biomes.size():
#for biome in currentMission.biomes[prio]:
#if biome.name == biomeName:
#return biome
#return Biome.new("empty",RoomList.new(),RoomData.new(),0,0)
#
#func generateBiomePos(biome: String,starterRoomSize: Vector2i) -> Vector2i:
#var genPos: Vector2i
#var possiblePos: Array[Vector2i]
#
##Find all possible Pos without a biome
#for x in levelGrid.size() - starterRoomSize.x - 1:
#for y in levelGrid[x].size() - starterRoomSize.y - 1:
#if !levelGrid[x][y].biome:
#possiblePos.push_back(levelGrid[x][y].position)
#
##Go through all pos untill one works
#genPos = possiblePos[rng.randi_range(0,possiblePos.size()-1)]
#while checkBiomeOverlap(biome,genPos,starterRoomSize.x,starterRoomSize.y):
#possiblePos.erase(genPos)
#if possiblePos.size() == 0:
#abandonSeed()
#break
#genPos = possiblePos[rng.randi_range(0,possiblePos.size()-1)]
#
#return genPos
#
#func placeBiomes(biomes: Array[Biome]) -> Array[DoorPosition]:
#var returnDoorLists: Array[DoorPosition] = []
#
#for biome in biomes:
#var starterRoomSize: Vector2i = Vector2i(biome.starterRoom.roomGrid.size(),biome.starterRoom.roomGrid[0].size())
#var generatePos: Vector2i = generateBiomePos(biome.name,starterRoomSize)
#changeBiomeArea2D(biome.name,generatePos,starterRoomSize.x,starterRoomSize.y)
#
##Spawn Starter room and add doors to list
#var doorList: Array[DoorPosition]
#doorList = spawnRoom(biome.starterRoom,generatePos,rng.randi_range(0,3))
#returnDoorLists += doorList
#
##If first Biome, set Starting Position
#if shipLogic.playerStartPos == Vector3(0,0,0):
#shipLogic.playerStartPos = Vector3(generatePos.x + biome.starterRoom.roomGrid.size()/2,0,generatePos.y + biome.starterRoom.roomGrid[0].size()/2) + self.position
#
#return returnDoorLists
#
#func fillCell(cellBiome: String,pos: Vector2i) -> GridCell:
#if isOutOfArray2DBounds(levelGrid.size(),levelGrid[0].size(),pos): return
#if !levelGrid[pos.x][pos.y].biome:
#levelGrid[pos.x][pos.y].biome = cellBiome
#return levelGrid[pos.x][pos.y]
#return
#
#func spreadCell(cell: GridCell,pos: Vector2i) -> Array[GridCell]:
#var returnCells: Array[GridCell] = []
#returnCells.push_back(fillCell(cell.biome,pos + Vector2i(0,-1)))
#returnCells.push_back(fillCell(cell.biome,pos + Vector2i(1,0)))
#returnCells.push_back(fillCell(cell.biome,pos + Vector2i(0,1)))
#returnCells.push_back(fillCell(cell.biome,pos + Vector2i(-1,0)))
#while returnCells.has(null):
#returnCells.erase(null)
#return returnCells
#
#func allCellsHaveBiome() -> bool:
#for x in levelGrid.size():
#for cell in levelGrid[x]:
#if !cell.biome: return false
#return true
#
#func spreadBiomes() -> void:
##Get all current biome grid cells -> Put them in starterCells
#var startCells: Array[GridCell] = []
#var startProbabilities: PackedFloat32Array = []
#for x in levelGrid.size():
#for y in levelGrid[x].size():
#if levelGrid[x][y].biome:
#var cell: GridCell = levelGrid[x][y]
#startCells.push_back(cell)
#startProbabilities.push_back(getBiome(cell.biome).spread)
#
#
##Spread them by one -> put the new ones in a new array
#while !(startCells.is_empty() or startProbabilities.is_empty()):
#var newCells: Array[GridCell] = []
#var newProbabilities: PackedFloat32Array = []
#var randomCellIndex: int = rng.rand_weighted(startProbabilities)
#
#if randomCellIndex == -1:
#randomCellIndex = startProbabilities.size()-1
#
#var cell: GridCell = startCells[randomCellIndex]
#
#newCells += spreadCell(cell,cell.position)
#for newCell in newCells:
#newProbabilities.push_back(getBiome(newCell.biome).spread)
#
##New cells now contains all that were newly assigned a biome and the ones that didnt spread
#startCells.remove_at(randomCellIndex)
#startProbabilities.remove_at(randomCellIndex)
#
#startCells += newCells
#startProbabilities += newProbabilities
#
##Astar
#func generateAstarPoints(findAllSpaceTakenCells: bool = false) -> void:
#var currentID: int = 0
#for x in levelGrid.size():
#for y in levelGrid[x].size():
#if (levelGrid[x][y].spaceTaken == findAllSpaceTakenCells) and !(x == 0 or x == gridSize-1 or y == 0 or y == gridSize-1):
#astar.add_point(currentID,Vector2i(x,y))
#currentID += 1
#
#func connectAstarPoints() -> void:
#for point in astar.get_point_ids():
#var possibleNeighbors: Array[int] = [point+1,point-1,point-gridSize,point+gridSize]
#
#for posNeigh in possibleNeighbors:
#if astar.has_point(posNeigh):
#astar.connect_points(point,posNeigh,true)
#
#func weightAstarPoints() -> void:
#for point in astar.get_point_ids():
#if astar.get_point_connections(point).size() != 4:
#astar.set_point_weight_scale(point,10)
#
#func posToID(pos: Vector2i) -> int:
#return gridSize*pos.x + pos.y
#
##Generating Biome Connections
#func chooseBiomeExits() -> void:
#var existingBiomes: Array[String] = []
#var currentBiomeExits: Array[BiomeExit] = []
#var choosenBiomeExits: Array[BiomeExit] = []
## Find What Biomes are Present
#for x in levelGrid.size():
#for y in levelGrid[x].size():
#if !existingBiomes.has(levelGrid[x][y].biome) and levelGrid[x][y].biome != "buffer":
#existingBiomes.push_back(levelGrid[x][y].biome)
#
##For each biome choose a number of exit
#for i in existingBiomes.size():
##Look through all exits for exits belonging to this biome
#for exit in biomeExitPositions:
#if exit.biome == existingBiomes[i]:
#currentBiomeExits.push_back(exit)
#biomeExitPositions.erase(exit)
#
##For each other biome, choose an exit
#
#for n in existingBiomes.size()-1:
#if currentBiomeExits:
## Randomly determine an exit
#var exit: BiomeExit = currentBiomeExits[rng.randi_range(0,currentBiomeExits.size()-1)]
#
##Test if exit was already choosen
#if !choosenBiomeExits.has(exit):
#choosenBiomeExits.push_back(exit)
#
#currentBiomeExits.clear()
#
##Get rid of all other exits
#biomeExitPositions = choosenBiomeExits
#
#func doorsAtBiomeExits() -> void:
#for exit in biomeExitPositions:
#levelGrid[exit.pos.x][exit.pos.y].door = false
#
#func generateConnectionPath() -> PackedVector2Array:
#var returnArray: PackedVector2Array = []
#
##Look through all exits and find the closest other exit
#for exit in biomeExitPositions:
#var newPath: PackedVector2Array = []
#var closestPointPath: PackedVector2Array = []
#for otherExit in biomeExitPositions:
#newPath = astar.get_point_path(posToID(exit.pos),posToID(otherExit.pos))
#if exit.biome != otherExit.biome and newPath.size() < closestPointPath.size() or closestPointPath.size() == 0:
#closestPointPath = newPath
#
##Connect the exits
#if closestPointPath.size() == 0:
#levelGrid[exit.pos.x][exit.pos.y].door = true
#else:
#returnArray += closestPointPath
#
#return returnArray
#
#func addFloorPos(gridCell: GridCell) -> void:
#if !gridCell.biomeConnection and !gridCell.spaceTaken:
#connectPathPositions.push_back(gridCell.position)
#gridCell.biomeConnection = true
#gridCell.spaceTaken = true
#
#func generateFloorPositions(spread: int = 2) -> void:
#for x in spread:
#for y in connectPathPositions.size():
#var fPos: Vector2i = connectPathPositions[y]
#levelGrid[fPos.x][fPos.y].spaceTaken = true
#levelGrid[fPos.x][fPos.y].biomeConnection = true
#addFloorPos(levelGrid[clampi(fPos.x+1,0,gridSize-1)][fPos.y])
#addFloorPos(levelGrid[fPos.x][clampi(fPos.y+1,0,gridSize-1)])
#addFloorPos(levelGrid[clampi(fPos.x-1,0,gridSize-1)][fPos.y])
#addFloorPos(levelGrid[fPos.x][clampi(fPos.y-1,0,gridSize-1)])
#
#func placeFloorPositionTiles() -> void:
#for tilePos in connectPathPositions:
#addObject(tile,self,Vector3(tilePos.x+0.5,0,tilePos.y+0.5))
#
#if rng.randf_range(0,1) > 0.9:
#shipLogic.hallwayLights.push_back(addObject(lamp,self,Vector3(tilePos.x+0.5,2.5,tilePos.y+0.5)))
#
#func spawnWallSegment(pos: Vector2i,rot: int) -> void:
#addObject(tileWall,self,Vector3(pos.x+0.5,0,pos.y+0.5),Vector3(0,rot*PI/2,0))
#
#func spawnCornerSegment(pos: Vector2i,rot: int) -> void:
#addObject(tileCorner,self,Vector3(pos.x+0.5,0,pos.y+0.5),Vector3(0,rot*PI/2,0))
#
#func placeWallsAlongTiles() -> void:
#for x in levelGrid.size():
#for y in levelGrid[x].size():
#if !levelGrid[x][y].biomeConnection: continue
##Walls
#if x+1 != levelGrid.size():
#if !levelGrid[x+1][y].spaceTaken: spawnWallSegment(Vector2i(x,y),3)
#else: spawnWallSegment(Vector2i(x,y),3)
#if x != 0:
#if !levelGrid[x-1][y].spaceTaken: spawnWallSegment(Vector2i(x,y),1)
#else: spawnWallSegment(Vector2i(x,y),1)
#if y+1 != levelGrid.size():
#if !levelGrid[x][y+1].spaceTaken: spawnWallSegment(Vector2i(x,y),2)
#else: spawnWallSegment(Vector2i(x,y),2)
#if y != 0:
#if !levelGrid[x][y-1].spaceTaken: spawnWallSegment(Vector2i(x,y),0)
#else: spawnWallSegment(Vector2i(x,y),0)
##Corners
#if x+1 != levelGrid.size() and y+1 != levelGrid.size():
#if !levelGrid[x+1][y+1].spaceTaken: spawnCornerSegment(Vector2i(x,y),3)
#else: spawnCornerSegment(Vector2i(x,y),3)
#if x != 0 and y != 0:
#if !levelGrid[x-1][y-1].spaceTaken: spawnCornerSegment(Vector2i(x,y),1)
#else: spawnCornerSegment(Vector2i(x,y),1)
#if x+1 != levelGrid.size() and y != 0:
#if !levelGrid[x+1][y-1].spaceTaken: spawnCornerSegment(Vector2i(x,y),0)
#else: spawnCornerSegment(Vector2i(x,y),0)
#if y+1 != levelGrid.size() and x != 0:
#if !levelGrid[x-1][y+1].spaceTaken: spawnCornerSegment(Vector2i(x,y),2)
#else: spawnCornerSegment(Vector2i(x,y),2)
#
##Debug Functions
#func printLevelGrid() -> void:
#for x in levelGrid.size():
#for y in levelGrid[x].size():
#if levelGrid[x][y].biomeConnection:
#debugCubeAtPos(Vector2(x,y))
#
#func printBiomeGrid() -> void:
#for x in levelGrid.size():
#for y in levelGrid[x].size():
#if levelGrid[x][y].biome == "test":
#debugCubeAtPos(Vector2(x,y))
#
#func debugCubeAtPos(pos: Vector2):
#var debugCube: PackedScene = preload("res://test/debugCube.tscn")
#addObject(debugCube,self,Vector3(pos.x+0.5,0,pos.y+0.5))
#
#func showAstarPoints() -> void:
#for point in astar.get_point_ids():
#var point_pos: Vector2i = astar.get_point_position(point)
#debugCubeAtPos(point_pos)