Files
tankwar_proj/js/data/LevelData.js
2026-04-10 22:59:39 +08:00

526 lines
18 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* LevelData.js
* Predefined level map configurations.
* Each level is a 13×21 grid (rows × cols). Values correspond to TERRAIN enum:
* 0=EMPTY, 1=BRICK, 2=STEEL, 3=RIVER, 4=FOREST, 5=BASE, 6=BASE_WALL
*
* In landscape mode the map is 13 rows × 21 cols.
* The original 13×13 design sits in the center (cols 416),
* with additional terrain on the flanks (cols 03 and cols 1720).
*
* Player spawns at bottom area, enemies spawn from top row.
* Base (5) is at bottom-center, surrounded by BASE_WALL (6).
*/
const LEVELS = [
// ============================================================
// Level 1 - Tutorial: open terrain, few bricks
// ============================================================
{
id: 1,
name: 'Tutorial I',
grid: [
//0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,1,0,0,0,1,0,0,1,0,1,0,0,1,0,0,0,1,0,0],
[0,0,0,0,0,0,1,0,0,1,0,1,0,0,1,0,0,0,0,0,0],
[0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0],
[0,0,0,0,0,0,1,0,1,1,0,1,1,0,1,0,0,0,0,0,0],
[0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0],
[0,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,0],
[0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0],
[0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,1,0],
[0,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,0],
[0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,6,6,5,6,6,0,0,0,0,0,0,0,0],
],
enemies: {
total: 20,
composition: { normal: 18, fast: 2, armor: 0, boss: 0 },
},
speedMultiplier: 0.6,
spawnPoints: [
{ col: 0, row: 0 },
{ col: 10, row: 0 },
{ col: 20, row: 0 },
],
playerSpawn: { col: 8, row: 10 },
},
// ============================================================
// Level 2 - Tutorial II: more bricks, simple layout
// ============================================================
{
id: 2,
name: 'Tutorial II',
grid: [
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,1,0,0,0,1,1,0,1,1,0,1,1,0,1,1,0,0,0,1,0],
[0,0,0,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,1,0,0,1,0,0,1,0,1,0,1,0,1,0,0,1,0,0,1,0],
[0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0],
[0,0,1,0,0,1,0,0,0,1,0,1,0,0,0,1,0,0,1,0,0],
[0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0],
[0,0,0,0,0,0,0,1,0,1,0,1,0,1,0,0,0,0,0,0,0],
[0,1,0,1,0,0,0,1,0,1,0,1,0,1,0,0,0,1,0,1,0],
[0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0],
[0,0,0,0,0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,6,6,5,6,6,0,0,0,0,0,0,0,0],
],
enemies: {
total: 20,
composition: { normal: 16, fast: 4, armor: 0, boss: 0 },
},
spawnPoints: [
{ col: 0, row: 0 },
{ col: 10, row: 0 },
{ col: 20, row: 0 },
],
playerSpawn: { col: 8, row: 10 },
},
// ============================================================
// Level 3 - Tutorial III: denser bricks, introduce forest
// ============================================================
{
id: 3,
name: 'Tutorial III',
grid: [
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,4,0,0,0,1,0,4,0,1,0,1,0,4,0,1,0,0,0,4,0],
[0,4,0,1,0,1,0,4,0,1,0,1,0,4,0,1,0,1,0,4,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,1,0,0,1,1,0,1,0,4,0,1,0,1,1,0,0,1,0,0],
[0,0,0,0,0,0,0,0,1,0,4,0,1,0,0,0,0,0,0,0,0],
[0,1,0,1,1,0,1,0,0,0,0,0,0,0,1,0,1,1,0,1,0],
[0,0,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,0,0],
[0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0],
[0,1,0,0,0,1,0,1,0,0,0,0,0,1,0,1,0,0,0,1,0],
[0,0,0,1,0,1,0,1,0,0,0,0,0,1,0,1,0,1,0,0,0],
[0,0,0,0,0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,6,6,5,6,6,0,0,0,0,0,0,0,0],
],
enemies: {
total: 20,
composition: { normal: 14, fast: 6, armor: 0, boss: 0 },
},
spawnPoints: [
{ col: 0, row: 0 },
{ col: 10, row: 0 },
{ col: 20, row: 0 },
],
playerSpawn: { col: 8, row: 10 },
},
// ============================================================
// Level 4 - Steel Fortress: steel walls appear
// ============================================================
{
id: 4,
name: 'Steel Fortress',
grid: [
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,2,0,0,1,2,0,1,1,0,1,1,0,2,1,0,0,2,0,0],
[0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0],
[0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,1,0],
[0,0,0,0,2,0,0,1,0,2,0,2,0,1,0,0,2,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,2,0,0,0,1,1,0,2,1,0,1,2,0,1,1,0,0,0,2,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,1,0,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,0,0],
[0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,1,0,0,0,0,0],
[0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0],
[0,0,0,0,0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,6,6,5,6,6,0,0,0,0,0,0,0,0],
],
enemies: {
total: 20,
composition: { normal: 12, fast: 5, armor: 3, boss: 0 },
},
spawnPoints: [
{ col: 0, row: 0 },
{ col: 10, row: 0 },
{ col: 20, row: 0 },
],
playerSpawn: { col: 8, row: 10 },
},
// ============================================================
// Level 5 - River Crossing: introduces water terrain
// ============================================================
{
id: 5,
name: 'River Crossing',
grid: [
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0],
[0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,0,0],
[0,1,0,0,0,0,0,3,3,0,1,0,3,3,0,0,0,0,0,1,0],
[0,0,0,1,0,1,0,3,3,0,0,0,3,3,0,1,0,1,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,1,0,0,1,0,1,0,3,1,0,1,3,0,1,0,1,0,0,1,0],
[0,0,0,0,0,0,0,0,3,0,0,0,3,0,0,0,0,0,0,0,0],
[0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,1,0,0],
[0,1,0,0,0,1,0,1,0,1,1,1,0,1,0,1,0,0,0,1,0],
[0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0],
[0,0,0,0,0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,6,6,5,6,6,0,0,0,0,0,0,0,0],
],
enemies: {
total: 20,
composition: { normal: 10, fast: 6, armor: 4, boss: 0 },
},
spawnPoints: [
{ col: 0, row: 0 },
{ col: 10, row: 0 },
{ col: 20, row: 0 },
],
playerSpawn: { col: 8, row: 10 },
},
// ============================================================
// Level 10 - Iron Wall: lots of armored enemies
// ============================================================
{
id: 10,
name: 'Iron Wall',
grid: [
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,2,0,0,0,2,1,0,2,1,0,1,2,0,1,2,0,0,0,2,0],
[0,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,1,0,0,1,2,0,1,3,3,0,3,3,1,0,2,1,0,0,1,0],
[0,0,0,0,0,0,0,1,3,3,0,3,3,1,0,0,0,0,0,0,0],
[0,0,2,0,0,1,0,0,0,2,0,2,0,0,0,1,0,0,2,0,0],
[0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0],
[0,1,0,1,0,0,0,2,0,1,4,1,0,2,0,0,0,1,0,1,0],
[0,0,0,0,0,1,0,0,0,1,4,1,0,0,0,1,0,0,0,0,0],
[0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0],
[0,0,0,0,0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,6,6,5,6,6,0,0,0,0,0,0,0,0],
],
enemies: {
total: 20,
composition: { normal: 6, fast: 4, armor: 10, boss: 0 },
},
spawnPoints: [
{ col: 0, row: 0 },
{ col: 10, row: 0 },
{ col: 20, row: 0 },
],
playerSpawn: { col: 8, row: 10 },
},
// ============================================================
// Level 20 - Boss Battle: giant tank encounter
// ============================================================
{
id: 20,
name: 'Boss Battle',
grid: [
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,1,0,0,1,2,0,1,2,0,2,1,0,2,1,0,0,1,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,2,0,0,2,0,0,2,3,0,0,0,3,2,0,0,2,0,0,2,0],
[0,0,0,0,0,0,0,0,3,0,4,0,3,0,0,0,0,0,0,0,0],
[0,0,1,0,0,1,2,0,0,0,4,0,0,0,2,1,0,0,1,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,1,0,0,0,2,0,1,0,2,0,2,0,1,0,2,0,0,0,1,0],
[0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,6,6,6,6,6,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,6,6,5,6,6,0,0,0,0,0,0,0,0],
],
enemies: {
total: 20,
composition: { normal: 8, fast: 4, armor: 6, boss: 2 },
},
spawnPoints: [
{ col: 0, row: 0 },
{ col: 10, row: 0 },
{ col: 20, row: 0 },
],
playerSpawn: { col: 8, row: 10 },
},
];
/**
* Get level data by level number.
* If the level doesn't exist, generate one based on the closest template
* with increased difficulty.
* @param {number} levelNum
* @returns {object} Level data
*/
function getLevelData(levelNum) {
// Direct match
const exact = LEVELS.find((l) => l.id === levelNum);
if (exact) return JSON.parse(JSON.stringify(exact));
// Find the closest template (highest id <= levelNum)
let template = LEVELS[0];
for (const l of LEVELS) {
if (l.id <= levelNum && l.id > template.id) {
template = l;
}
}
// Clone and adjust difficulty
const data = JSON.parse(JSON.stringify(template));
data.id = levelNum;
data.name = `Level ${levelNum}`;
// Scale enemy composition based on level
const cycle = Math.floor((levelNum - 1) / 20); // difficulty cycle
const extra = cycle * 2;
data.enemies.composition.armor = Math.min(
data.enemies.total,
data.enemies.composition.armor + extra
);
data.enemies.composition.fast = Math.min(
data.enemies.total - data.enemies.composition.armor,
data.enemies.composition.fast + cycle
);
data.enemies.composition.normal = Math.max(
0,
data.enemies.total -
data.enemies.composition.armor -
data.enemies.composition.fast -
data.enemies.composition.boss
);
return data;
}
// ============================================================
// PVP Maps - Symmetric layouts with bases for 1v1 base-destruction mode
// Each player has a base (TERRAIN.BASE=5) surrounded by BASE_WALL (6)
// Player 1 base on left, Player 2 base on right
// ============================================================
const PVP_MAPS = [
{
id: 1,
name: 'Arena I',
grid: [
//0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0],
[0,0,0,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0],
[0,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,0],
[0,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,0],
[0,6,5,6,1,0,1,0,2,0,0,0,2,0,1,0,1,6,5,6,0],
[0,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,0],
[0,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,0],
[0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0],
[0,0,0,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
],
teamABase: [{ col: 2, row: 6 }],
teamBBase: [{ col: 18, row: 6 }],
teamASpawns: [{ col: 1, row: 5 }],
teamBSpawns: [{ col: 19, row: 7 }],
},
{
id: 2,
name: 'Arena II',
grid: [
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0],
[0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,2,1,0,0,0,1,2,1,0,0,0,0,0,0],
[0,0,0,0,0,0,0,1,0,0,4,0,0,1,0,0,0,0,0,0,0],
[0,6,6,0,0,1,0,0,0,1,4,1,0,0,0,1,0,0,6,6,0],
[0,6,5,6,0,0,0,0,4,4,0,4,4,0,0,0,0,6,5,6,0],
[0,6,6,0,0,1,0,0,0,1,4,1,0,0,0,1,0,0,6,6,0],
[0,0,0,0,0,0,0,1,0,0,4,0,0,1,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,2,1,0,0,0,1,2,1,0,0,0,0,0,0],
[0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0],
[0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
],
teamABase: [{ col: 2, row: 6 }],
teamBBase: [{ col: 18, row: 6 }],
teamASpawns: [{ col: 0, row: 6 }],
teamBSpawns: [{ col: 20, row: 6 }],
},
{
id: 3,
name: 'Arena III',
grid: [
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,1,0,0,2,0,0,0,0,0,2,0,0,1,0,0,0,0],
[0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,0,3,0,0,0,3,0,1,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,3,0,2,0,3,0,0,0,0,0,0,0,0],
[0,6,6,1,0,2,0,0,0,0,0,0,0,0,0,2,0,1,6,6,0],
[0,6,5,6,0,0,0,1,0,4,4,4,0,1,0,0,0,6,5,6,0],
[0,6,6,1,0,2,0,0,0,0,0,0,0,0,0,2,0,1,6,6,0],
[0,0,0,0,0,0,0,0,3,0,2,0,3,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,0,3,0,0,0,3,0,1,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0],
[0,0,0,0,1,0,0,2,0,0,0,0,0,2,0,0,1,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
],
teamABase: [{ col: 2, row: 6 }],
teamBBase: [{ col: 18, row: 6 }],
teamASpawns: [{ col: 1, row: 5 }],
teamBSpawns: [{ col: 19, row: 7 }],
},
];
/**
* Get a PVP map by id, or deterministically by roomId seed.
* When no mapId is given, uses roomId to pick the same map on both clients.
* Falls back to random only when neither mapId nor roomId is provided.
* @param {number} [mapId] - Explicit map id
* @param {string} [roomId] - Room id used as seed for deterministic selection
* @returns {object} PVP map data (deep clone).
*/
function getPvpMap(mapId, roomId) {
let map;
if (mapId) {
map = PVP_MAPS.find((m) => m.id === mapId);
}
if (!map && roomId) {
// Deterministic selection based on roomId so both clients pick the same map
let hash = 0;
for (let i = 0; i < roomId.length; i++) {
hash = ((hash << 5) - hash + roomId.charCodeAt(i)) | 0;
}
const index = Math.abs(hash) % PVP_MAPS.length;
map = PVP_MAPS[index];
}
if (!map) {
map = PVP_MAPS[Math.floor(Math.random() * PVP_MAPS.length)];
}
return JSON.parse(JSON.stringify(map));
}
// ============================================================
// 3v3 Team Maps - Symmetric layouts with bases on both ends
// Each team has a base (TERRAIN.BASE=5) surrounded by BASE_WALL (6)
// Left team base at left end, right team base at right end
// Center area is the contested zone
// ============================================================
const TEAM_MAPS = [
{
id: 1,
name: 'Battlefield I',
grid: [
//0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,0,0],
[0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0],
[0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0],
[0,0,0,0,1,0,0,1,0,2,0,2,0,1,0,0,1,0,0,0,0],
[0,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,0],
[0,6,5,6,0,2,0,0,3,3,0,3,3,0,0,2,0,6,5,6,0],
[0,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,0],
[0,0,0,0,1,0,0,1,0,2,0,2,0,1,0,0,1,0,0,0,0],
[0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0],
[0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0],
[0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
],
// Each team has exactly 1 base, centered vertically on their side
teamABase: [{ col: 2, row: 6 }],
teamBBase: [{ col: 18, row: 6 }],
// Spawn points for Team A (left side, near base)
teamASpawns: [
{ col: 1, row: 5 },
{ col: 0, row: 6 },
{ col: 1, row: 7 },
],
// Spawn points for Team B (right side, near base)
teamBSpawns: [
{ col: 19, row: 5 },
{ col: 20, row: 6 },
{ col: 19, row: 7 },
],
},
{
id: 2,
name: 'Battlefield II',
grid: [
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,0,0,4,0,4,0,0,1,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,1,4,0,4,1,0,0,0,0,0,0,0,0],
[0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0],
[0,0,0,0,0,0,0,2,0,1,0,1,0,2,0,0,0,0,0,0,0],
[0,6,6,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,6,6,0],
[0,6,5,6,1,0,2,0,0,0,3,0,0,0,2,0,1,6,5,6,0],
[0,6,6,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,6,6,0],
[0,0,0,0,0,0,0,2,0,1,0,1,0,2,0,0,0,0,0,0,0],
[0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0],
[0,0,0,0,0,0,0,0,1,4,0,4,1,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,0,0,4,0,4,0,0,1,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
],
teamABase: [{ col: 2, row: 6 }],
teamBBase: [{ col: 18, row: 6 }],
teamASpawns: [
{ col: 1, row: 5 },
{ col: 0, row: 6 },
{ col: 1, row: 7 },
],
teamBSpawns: [
{ col: 19, row: 5 },
{ col: 20, row: 6 },
{ col: 19, row: 7 },
],
},
{
id: 3,
name: 'Battlefield III',
grid: [
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,1,0,0,2,0,0,0,0,0,2,0,0,1,0,0,0,0],
[0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,0,3,0,0,0,3,0,1,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,3,0,2,0,3,0,0,0,0,0,0,0,0],
[0,6,6,1,0,2,0,0,0,0,0,0,0,0,0,2,0,1,6,6,0],
[0,6,5,6,0,0,0,1,0,4,4,4,0,1,0,0,0,6,5,6,0],
[0,6,6,1,0,2,0,0,0,0,0,0,0,0,0,2,0,1,6,6,0],
[0,0,0,0,0,0,0,0,3,0,2,0,3,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,0,3,0,0,0,3,0,1,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0],
[0,0,0,0,1,0,0,2,0,0,0,0,0,2,0,0,1,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
],
teamABase: [{ col: 2, row: 6 }],
teamBBase: [{ col: 18, row: 6 }],
teamASpawns: [
{ col: 1, row: 5 },
{ col: 0, row: 6 },
{ col: 1, row: 7 },
],
teamBSpawns: [
{ col: 19, row: 5 },
{ col: 20, row: 6 },
{ col: 19, row: 7 },
],
},
];
/**
* Get a 3v3 team map by id or random.
* @param {number} [mapId] - Optional map id
* @returns {object} Team map data (deep clone).
*/
function getTeamMap(mapId) {
let map;
if (mapId) {
map = TEAM_MAPS.find((m) => m.id === mapId);
}
if (!map) {
map = TEAM_MAPS[Math.floor(Math.random() * TEAM_MAPS.length)];
}
return JSON.parse(JSON.stringify(map));
}
module.exports = { LEVELS, getLevelData, PVP_MAPS, getPvpMap, TEAM_MAPS, getTeamMap };