fix: Implement NukeWars gamemode fixes

- Fix NukeWars not being treated as a teams game (always 2 teams)
- Fix building restrictions during/after preparation phase
  * Block only MIRVs completely
  * Block nuclear weapons during preparation phase only
  * Allow all other structures
- Fix transport boat movement rules
  * Allow movement within team territory
  * Block movement into enemy territory
- Add proper preparation phase (180 seconds)
- Ensure combat is primarily through nuclear weapons

Technical changes:
- Add NukeWars to GameMode enum
- Implement preparation phase configuration and timing
- Add team territory checks for transport boats
- Fix building restriction logic for NukeWars mode
This commit is contained in:
Restart2008
2025-10-25 11:03:29 -07:00
parent b10cadff20
commit 3e5a1242e4
5 changed files with 30 additions and 21 deletions
+1
View File
@@ -89,6 +89,7 @@ export interface Config {
donateTroops(): boolean;
instantBuild(): boolean;
numSpawnPhaseTurns(): number;
numPreparationPhaseTurns(): number;
userSettings(): UserSettings;
playerTeams(): TeamCountConfig;
+1 -3
View File
@@ -622,8 +622,6 @@ export class DefaultConfig implements Config {
numSpawnPhaseTurns(): number {
return this._gameConfig.gameType === GameType.Singleplayer ? 100 : 300;
}
<<<<<<< Updated upstream
=======
numPreparationPhaseTurns(): number {
if (this._gameConfig.gameMode === GameMode.NukeWars) {
@@ -631,7 +629,7 @@ export class DefaultConfig implements Config {
}
return 0;
}
>>>>>>> Stashed changes
numBots(): number {
return this.bots();
}
+1
View File
@@ -151,6 +151,7 @@ export const isGameType = (value: unknown): value is GameType =>
export enum GameMode {
FFA = "Free For All",
Team = "Team",
NukeWars = "Nuke Wars"
}
export const isGameMode = (value: unknown): value is GameMode =>
isEnumValue(GameMode, value);
-12
View File
@@ -96,12 +96,7 @@ export class GameImpl implements Game {
this._width = _map.width();
this._height = _map.height();
this.unitGrid = new UnitGrid(this._map);
<<<<<<< Updated upstream
if (_config.gameConfig().gameMode === GameMode.Team) {
=======
if (this.isTeamBasedGame()) {
>>>>>>> Stashed changes
this.populateTeams();
}
this.addPlayers();
@@ -114,12 +109,9 @@ export class GameImpl implements Game {
private populateTeams() {
let numPlayerTeams = this._config.playerTeams();
<<<<<<< Updated upstream
=======
if (this._config.gameConfig().gameMode === GameMode.NukeWars) {
numPlayerTeams = 2;
}
>>>>>>> Stashed changes
if (typeof numPlayerTeams !== "number") {
const players = this._humans.length + this._nations.length;
switch (numPlayerTeams) {
@@ -338,15 +330,11 @@ export class GameImpl implements Game {
return this._ticks <= this.config().numSpawnPhaseTurns();
}
<<<<<<< Updated upstream
=======
inPreparationPhase(): boolean {
const spawn = this.config().numSpawnPhaseTurns();
const prep = this.config().numPreparationPhaseTurns();
return this._ticks > spawn && this._ticks <= spawn + prep;
}
>>>>>>> Stashed changes
ticks(): number {
return this._ticks;
}
+27 -6
View File
@@ -950,6 +950,22 @@ export class PlayerImpl implements Player {
);
}
private isInTeamSpawnZone(tile: TileRef): boolean {
const team = this.team();
if (!team) return false;
// Simple geometric split:
// Team 1 gets left half (x < width/2)
// Team 2 gets right half (x >= width/2)
const x = this.mg.x(tile);
const mapWidth = this.mg.width();
const midpoint = Math.floor(mapWidth / 2);
// Team 1 gets left half, Team 2 gets right half
const isTeam1 = team === this.mg.teams()[0];
return isTeam1 ? x < midpoint : x >= midpoint;
}
private canBuildShipNukeWars(
unitType: UnitType,
targetTile: TileRef,
@@ -974,6 +990,17 @@ export class PlayerImpl implements Player {
}
private canBuildNukeNukeWars(unitType: UnitType): boolean {
// Always block MIRVs in NukeWars
if (unitType === UnitType.MIRV) {
this.mg.displayMessage(
"MIRVs are not allowed in Nuke Wars mode",
MessageType.ATTACK_FAILED,
this.id(),
);
return false;
}
// Block nuclear weapons during preparation phase
if (
(unitType === UnitType.AtomBomb || unitType === UnitType.HydrogenBomb) &&
this.mg.inPreparationPhase()
@@ -998,8 +1025,6 @@ export class PlayerImpl implements Player {
return false;
}
<<<<<<< Updated upstream
=======
if (this.isNukeWarsAndBaikal()) {
if (!this.canBuildShipNukeWars(unitType, targetTile)) {
return false;
@@ -1017,7 +1042,6 @@ export class PlayerImpl implements Player {
}
}
>>>>>>> Stashed changes
const cost = this.mg.unitInfo(unitType).cost(this);
if (!this.isAlive() || this.gold() < cost) {
return false;
@@ -1031,12 +1055,9 @@ export class PlayerImpl implements Player {
return this.nukeSpawn(targetTile);
case UnitType.AtomBomb:
case UnitType.HydrogenBomb:
<<<<<<< Updated upstream
=======
if (this.isNukeWars() && !this.canBuildNukeNukeWars(unitType)) {
return false;
}
>>>>>>> Stashed changes
return this.nukeSpawn(targetTile);
case UnitType.MIRVWarhead:
return targetTile;