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 23:12:24 +01:00
committed by GitHub
parent 4b917c4153
commit 339ace0bd6
13 changed files with 197 additions and 14 deletions
+21
View File
@@ -110,6 +110,27 @@ export class NationExecution implements Execution {
return;
}
// If team spawn areas are configured and the nation's spawn cell
// is outside its team's area, spawn randomly within the area instead.
const team = this.player.team();
if (team !== null) {
const area = this.mg.teamSpawnArea(team);
if (area !== undefined) {
const cell = this.nation.spawnCell;
const inArea =
cell.x >= area.x &&
cell.x < area.x + area.width &&
cell.y >= area.y &&
cell.y < area.y + area.height;
if (!inArea) {
this.mg.addExecution(
new SpawnExecution(this.gameID, this.nation.playerInfo),
);
return;
}
}
}
// Select a tile near the position defined in the map manifest
const rl = this.randomSpawnLand();
+25 -4
View File
@@ -1,4 +1,11 @@
import { Execution, Game, Player, PlayerInfo, PlayerType } from "../game/Game";
import {
Execution,
Game,
Player,
PlayerInfo,
PlayerType,
SpawnArea,
} from "../game/Game";
import { TileRef } from "../game/GameMap";
import { PseudoRandom } from "../PseudoRandom";
import { GameID } from "../Schemas";
@@ -90,12 +97,13 @@ export class SpawnExecution implements Execution {
return { center, tiles };
}
const spawnArea = this.getTeamSpawnArea();
let tries = 0;
while (tries < SpawnExecution.MAX_SPAWN_TRIES) {
tries++;
const center = this.randTile();
const center = this.randTile(spawnArea);
if (
!this.mg.isLand(center) ||
@@ -137,10 +145,23 @@ export class SpawnExecution implements Execution {
return;
}
private randTile(): TileRef {
private randTile(area?: SpawnArea): TileRef {
if (area) {
const x = this.random.nextInt(area.x, area.x + area.width);
const y = this.random.nextInt(area.y, area.y + area.height);
return this.mg.ref(x, y);
}
const x = this.random.nextInt(0, this.mg.width());
const y = this.random.nextInt(0, this.mg.height());
return this.mg.ref(x, y);
}
private getTeamSpawnArea(): SpawnArea | undefined {
const player = this.mg.player(this.playerInfo.id);
const team = player.team();
if (team === null) {
return undefined;
}
return this.mg.teamSpawnArea(team);
}
}