local ASCIIParser = require(script:GetCustomProperty("ASCIIParser"))
local TILES = require(script:GetCustomProperty("Tiles"))
local ENEMIES = require(script:GetCustomProperty("Enemies"))
local MapBuilder = {
Type = {}
}
for key, row in pairs(TILES) do
MapBuilder.Type[row.key] = row.id
end
function MapBuilder.Build(opts)
local map, mapStr = ASCIIParser.BuildMap(opts.map, opts.width, opts.height)
MapBuilder.Spawn(map, opts.width, opts.height, opts.size, opts.container)
end
function MapBuilder.GetTile(map, row, col)
local foundRow = map[row]
if foundRow then
return foundRow[col]
end
return nil
end
function MapBuilder.GetNeighbors(map, row, column)
return {
NORTH = MapBuilder.GetTile(map, row - 1, column),
SOUTH = MapBuilder.GetTile(map, row + 1, column),
EAST = MapBuilder.GetTile(map, row, column + 1),
WEST = MapBuilder.GetTile(map, row, column - 1)
}
end
function MapBuilder.CheckForWallCorner(map, neighbors, row, col)
local tileRow = nil
local extraTile = nil
local rotation = Rotation.New()
if neighbors.WEST == MapBuilder.Type.Wall and neighbors.NORTH == MapBuilder.Type.Wall and map[row][col] ~= MapBuilder.Type.Wall and neighbors.EAST ~= nil and neighbors.SOUTH ~= nil then
tileRow = TILES[MapBuilder.Type.WallCorner]
rotation.z = 0
elseif neighbors.NORTH == MapBuilder.Type.Wall and neighbors.EAST == MapBuilder.Type.Wall and map[row][col] ~= MapBuilder.Type.Wall and neighbors.WEST ~= nil and neighbors.SOUTH ~= nil then
tileRow = TILES[MapBuilder.Type.WallCorner]
rotation.z = 90
elseif neighbors.EAST == MapBuilder.Type.Wall and neighbors.SOUTH == MapBuilder.Type.Wall and map[row][col] ~= MapBuilder.Type.Wall and neighbors.NORTH ~= nil and neighbors.WEST ~= nil then
tileRow = TILES[MapBuilder.Type.WallCorner]
rotation.z = 180
elseif neighbors.SOUTH == MapBuilder.Type.Wall and neighbors.WEST == MapBuilder.Type.Wall and map[row][col] ~= MapBuilder.Type.Wall and neighbors.EAST ~= nil and neighbors.NORTH ~= nil then
tileRow = TILES[MapBuilder.Type.WallCorner]
rotation.z = 270
end
if tileRow ~= nil then
extraTile = TILES[MapBuilder.Type.Floor]
end
return tileRow, rotation, extraTile
end
function MapBuilder.CheckForDeadEnd(map, neighbors, row, col)
local tileRow = nil
local extraTile = nil
local rotation = Rotation.New()
if neighbors.WEST == MapBuilder.Type.Wall and neighbors.NORTH == MapBuilder.Type.Wall and neighbors.EAST == MapBuilder.Type.Wall and neighbors.SOUTH ~= MapBuilder.Type.Wall and map[row][col] ~= MapBuilder.Type.Wall then
tileRow = TILES[MapBuilder.Type.WallCorner]
rotation.z = 45
elseif neighbors.NORTH == MapBuilder.Type.Wall and neighbors.EAST == MapBuilder.Type.Wall and neighbors.SOUTH == MapBuilder.Type.Wall and neighbors.WEST ~= MapBuilder.Type.Wall and map[row][col] ~= MapBuilder.Type.Wall then
tileRow = TILES[MapBuilder.Type.WallCorner]
rotation.z = 135
elseif neighbors.EAST == MapBuilder.Type.Wall and neighbors.SOUTH == MapBuilder.Type.Wall and neighbors.WEST == MapBuilder.Type.Wall and neighbors.NORTH ~= MapBuilder.Type.Wall and map[row][col] ~= MapBuilder.Type.Wall then
tileRow = TILES[MapBuilder.Type.WallCorner]
rotation.z = -135
elseif neighbors.SOUTH == MapBuilder.Type.Wall and neighbors.WEST == MapBuilder.Type.Wall and neighbors.NORTH == MapBuilder.Type.Wall and neighbors.EAST ~= MapBuilder.Type.Wall and map[row][col] ~= MapBuilder.Type.Wall then
tileRow = TILES[MapBuilder.Type.WallCorner]
rotation.z = -45
end
if tileRow ~= nil then
extraTile = TILES[MapBuilder.Type.Floor]
end
return tileRow, rotation, extraTile
end
function MapBuilder.SpawnExtraTile(extraTile, params, container)
if extraTile == nil then
return
end
if MapBuilder.Type.Floor == extraTile.id then
params.scale.z = 1
params.rotation = Rotation.New()
end
container:SpawnSharedAsset(extraTile.tile, params)
end
function MapBuilder.SpawnPlayers(spawnPoint)
if spawnPoint == nil or not Environment.IsServer() then
return
end
Task.Wait()
Events.Broadcast("SpawnPlayers", spawnPoint, TILES[MapBuilder.Type.Spawn].rotation)
end
function MapBuilder.SpawnEnemies(spawnPoints, container)
for index, point in ipairs(spawnPoints) do
local enemyAsset = ENEMIES[math.random(#ENEMIES)].asset
local enemy = World.SpawnAsset(enemyAsset, {
position = point + (Vector3.UP * 50),
networkContext = NetworkContextType.NETWORKED,
rotation = Rotation.New(0, 0, math.random(0, 360))
})
end
end
function MapBuilder.GenerateNavMesh(width, height, size, container)
_G.NavMeshArea = {
scale = Vector3.New(size / 100 * height, size / 100 * width, size / 100),
position = Vector3.New(-size / 2, size / 2, size / 2)
}
Events.Connect("NavMeshProgress", function(v, isGrid)
if isGrid then
container:SetCustomProperty("grid", v)
else
container:SetCustomProperty("grid", 1)
container:SetCustomProperty("mesh", v)
end
end)
end
function MapBuilder.SpawnPlayersAndEnemies(spawnPoint, enemySpawnPoints, container)
Events.Connect("NavMeshGenerated", function()
container:SetCustomProperty("mesh", 1)
MapBuilder.SpawnEnemies(enemySpawnPoints)
MapBuilder.SpawnPlayers(spawnPoint)
end)
end
function MapBuilder.Spawn(map, width, height, size, container)
if not Environment.IsServer() then
return
end
local spawnPoint = nil
local enemySpawnPoints = {}
for row = 1, height do
for col = 1, width do
local tileRow, rotation, extraTile
local neighbors = MapBuilder.GetNeighbors(map, row, col)
tileRow, rotation, extraTile = MapBuilder.CheckForDeadEnd(map, neighbors, row, col)
if tileRow == nil then
tileRow, rotation, extraTile = MapBuilder.CheckForWallCorner(map, neighbors, row, col)
end
if tileRow == nil then
tileRow = TILES[map[row][col]]
end
if tileRow ~= nil then
local scale = Vector3.New(size / 100, size / 100, size / 100)
if tileRow.floor then
scale.z = 1
end
local x = -(row * size) + (height * size) / 2
local y = (col * size) - (width * size) / 2
local params = {
scale = scale,
position = Vector3.New(x, y, 0),
rotation = rotation
}
if tileRow.tile ~= nil then
container:SpawnSharedAsset(tileRow.tile, params)
end
if map[row][col] == MapBuilder.Type.Spawn then
spawnPoint = params.position
if extraTile == nil then
extraTile = TILES[MapBuilder.Type.Floor]
end
elseif map[row][col] == MapBuilder.Type.Enemy then
table.insert(enemySpawnPoints, params.position)
if extraTile == nil then
extraTile = TILES[MapBuilder.Type.Floor]
end
end
if extraTile ~= nil then
MapBuilder.SpawnExtraTile(extraTile, params, container)
end
end
end
end
MapBuilder.SpawnPlayersAndEnemies(spawnPoint, enemySpawnPoints, container)
MapBuilder.GenerateNavMesh(width, height, size, container)
end
return MapBuilder
Code language: Lua (lua)