v30 nuke wars preparation: Disable boats & Team spawn zones (#3263)

## Description:

Preparation for nuke wars, for v30.
Next PR will be adding the nuke wars modifier for public games, but
Wonders https://github.com/openfrontio/OpenFrontIO/pull/3224 needs to be
merged first to avoid merge conflicts.

### 1. Disable boats setting

It's possible to disable `UnitType.TransportShip` now. Because they are
not needed in nuke wars and can even be annoying.

<img width="720" height="320" alt="image"
src="https://github.com/user-attachments/assets/661bc10d-b204-4b4f-b876-ee7c9b92de8c"
/>

### 2. Team spawn zones for random spawn

Maps can have `teamGameSpawnAreas` in their json file now.
Spawn areas are currently active if 
- a supported map is chosen (Baikal Nuke Wars or Four Islands)
- a supported team size is chosen (2 teams on Baikal Nuke Wars or 2/4
teams on Four Islands)
- random spawn is enabled

## Please complete the following:

- [X] I have added screenshots for all UI updates
- [X] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [X] I have added relevant tests to the test directory
- [X] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

FloPinguin
This commit is contained in:
FloPinguin
2026-02-23 16:12:24 -06:00
committed by GitHub
parent 4b917c4153
commit 339ace0bd6
13 changed files with 197 additions and 14 deletions
+23 -4
View File
@@ -1,4 +1,4 @@
import { GameMapSize, GameMapType } from "./Game";
import { GameMapSize, GameMapType, TeamGameSpawnAreas } from "./Game";
import { GameMap, GameMapImpl } from "./GameMap";
import { GameMapLoader } from "./GameMapLoader";
@@ -6,9 +6,10 @@ export type TerrainMapData = {
nations: Nation[];
gameMap: GameMap;
miniGameMap: GameMap;
teamGameSpawnAreas?: TeamGameSpawnAreas;
};
const loadedMaps = new Map<GameMapType, TerrainMapData>();
const loadedMaps = new Map<string, TerrainMapData>();
export interface MapMetadata {
width: number;
@@ -22,6 +23,7 @@ export interface MapManifest {
map4x: MapMetadata;
map16x: MapMetadata;
nations: Nation[];
teamGameSpawnAreas?: TeamGameSpawnAreas;
}
export interface Nation {
@@ -35,7 +37,8 @@ export async function loadTerrainMap(
mapSize: GameMapSize,
terrainMapFileLoader: GameMapLoader,
): Promise<TerrainMapData> {
const cached = loadedMaps.get(map);
const cacheKey = `${map}:${mapSize}`;
const cached = loadedMaps.get(cacheKey);
if (cached !== undefined) return cached;
const mapFiles = terrainMapFileLoader.getMapData(map);
const manifest = await mapFiles.manifest();
@@ -62,12 +65,28 @@ export async function loadTerrainMap(
});
}
// Scale spawn areas for compact maps
let teamGameSpawnAreas = manifest.teamGameSpawnAreas;
if (mapSize === GameMapSize.Compact && teamGameSpawnAreas) {
const scaled: TeamGameSpawnAreas = {};
for (const [key, areas] of Object.entries(teamGameSpawnAreas)) {
scaled[key] = areas.map((a) => ({
x: Math.floor(a.x / 2),
y: Math.floor(a.y / 2),
width: Math.max(1, Math.floor(a.width / 2)),
height: Math.max(1, Math.floor(a.height / 2)),
}));
}
teamGameSpawnAreas = scaled;
}
const result = {
nations: manifest.nations,
gameMap: gameMap,
miniGameMap: miniMap,
teamGameSpawnAreas,
};
loadedMaps.set(map, result);
loadedMaps.set(cacheKey, result);
return result;
}