diff --git a/src/client/HostLobbyModal.ts b/src/client/HostLobbyModal.ts
index c356991fa..10fdc614a 100644
--- a/src/client/HostLobbyModal.ts
+++ b/src/client/HostLobbyModal.ts
@@ -18,6 +18,7 @@ export class HostLobbyModal extends LitElement {
@state() private selectedMap: GameMapType = GameMapType.World;
@state() private selectedDifficulty: Difficulty = Difficulty.Medium;
@state() private disableNPCs = false;
+ @state() private disableNukes: boolean = false;
@state() private bots: number = 400;
@state() private infiniteGold: boolean = false;
@state() private infiniteTroops: boolean = false;
@@ -506,6 +507,20 @@ export class HostLobbyModal extends LitElement {
/>
Infinite troops
+
+
@@ -621,6 +636,9 @@ export class HostLobbyModal extends LitElement {
this.infiniteTroops = Boolean((e.target as HTMLInputElement).checked);
this.putGameConfig();
}
+ private handleDisableNukesChange(e: Event) {
+ this.disableNukes = Boolean((e.target as HTMLInputElement).checked);
+ }
private async handleDisableNPCsChange(e: Event) {
this.disableNPCs = Boolean((e.target as HTMLInputElement).checked);
@@ -641,6 +659,7 @@ export class HostLobbyModal extends LitElement {
gameMap: this.selectedMap,
difficulty: this.selectedDifficulty,
disableNPCs: this.disableNPCs,
+ disableNukes: this.disableNukes,
bots: this.bots,
infiniteGold: this.infiniteGold,
infiniteTroops: this.infiniteTroops,
diff --git a/src/client/SinglePlayerModal.ts b/src/client/SinglePlayerModal.ts
index 23ef02c37..528c0dab2 100644
--- a/src/client/SinglePlayerModal.ts
+++ b/src/client/SinglePlayerModal.ts
@@ -16,6 +16,7 @@ export class SinglePlayerModal extends LitElement {
@state() private selectedMap: GameMapType = GameMapType.World;
@state() private selectedDifficulty: Difficulty = Difficulty.Medium;
@state() private disableNPCs: boolean = false;
+ @state() private disableNukes: boolean = false;
@state() private bots: number = 400;
@state() private infiniteGold: boolean = false;
@state() private infiniteTroops: boolean = false;
@@ -411,6 +412,20 @@ export class SinglePlayerModal extends LitElement {
/>
Infinite troops
+
+
@@ -464,6 +479,9 @@ export class SinglePlayerModal extends LitElement {
private handleDisableNPCsChange(e: Event) {
this.disableNPCs = Boolean((e.target as HTMLInputElement).checked);
}
+ private handleDisableNukesChange(e: Event) {
+ this.disableNukes = Boolean((e.target as HTMLInputElement).checked);
+ }
private getRandomMap(): GameMapType {
const maps = Object.values(GameMapType);
@@ -490,6 +508,7 @@ export class SinglePlayerModal extends LitElement {
gameType: GameType.Singleplayer,
difficulty: this.selectedDifficulty,
disableNPCs: this.disableNPCs,
+ disableNukes: this.disableNukes,
bots: this.bots,
infiniteGold: this.infiniteGold,
infiniteTroops: this.infiniteTroops,
diff --git a/src/client/graphics/layers/BuildMenu.ts b/src/client/graphics/layers/BuildMenu.ts
index 8afa0f1af..10c5388ed 100644
--- a/src/client/graphics/layers/BuildMenu.ts
+++ b/src/client/graphics/layers/BuildMenu.ts
@@ -96,6 +96,7 @@ export class BuildMenu extends LitElement implements Layer {
public eventBus: EventBus;
private clickedTile: TileRef;
private playerActions: PlayerActions | null;
+ private filteredBuildTable: BuildItemDisplay[][] = buildTable;
tick() {
if (!this._hidden) {
@@ -342,7 +343,7 @@ export class BuildMenu extends LitElement implements Layer {
class="build-menu ${this._hidden ? "hidden" : ""}"
@contextmenu=${(e) => e.preventDefault()}
>
- ${buildTable.map(
+ ${this.filteredBuildTable.map(
(row) => html`
${row.map(
@@ -407,6 +408,26 @@ export class BuildMenu extends LitElement implements Layer {
this.playerActions = actions;
this.requestUpdate();
});
+
+ // removed disabled buildings from the buildtable
+ this.filteredBuildTable = this.getBuildableUnits();
+ }
+
+ private getBuildableUnits(): BuildItemDisplay[][] {
+ if (this.game?.config()?.disableNukes()) {
+ return buildTable.map((row) =>
+ row.filter(
+ (item) =>
+ ![
+ UnitType.AtomBomb,
+ UnitType.MIRV,
+ UnitType.HydrogenBomb,
+ UnitType.MissileSilo,
+ ].includes(item.unitType),
+ ),
+ );
+ }
+ return buildTable;
}
get isVisible() {
diff --git a/src/core/Schemas.ts b/src/core/Schemas.ts
index bef3eea85..e430d63b2 100644
--- a/src/core/Schemas.ts
+++ b/src/core/Schemas.ts
@@ -108,6 +108,7 @@ const GameConfigSchema = z.object({
difficulty: z.nativeEnum(Difficulty),
gameType: z.nativeEnum(GameType),
disableNPCs: z.boolean(),
+ disableNukes: z.boolean(),
bots: z.number().int().min(0).max(400),
infiniteGold: z.boolean(),
infiniteTroops: z.boolean(),
diff --git a/src/core/configuration/Config.ts b/src/core/configuration/Config.ts
index e0cfc2d3a..1f0b50bc8 100644
--- a/src/core/configuration/Config.ts
+++ b/src/core/configuration/Config.ts
@@ -55,6 +55,7 @@ export interface Config {
percentageTilesOwnedToWin(): number;
numBots(): number;
spawnNPCs(): boolean;
+ disableNukes(): boolean;
bots(): number;
infiniteGold(): boolean;
infiniteTroops(): boolean;
diff --git a/src/core/configuration/DefaultConfig.ts b/src/core/configuration/DefaultConfig.ts
index f3e1612f3..1669e6a7b 100644
--- a/src/core/configuration/DefaultConfig.ts
+++ b/src/core/configuration/DefaultConfig.ts
@@ -148,6 +148,9 @@ export class DefaultConfig implements Config {
spawnNPCs(): boolean {
return !this._gameConfig.disableNPCs;
}
+ disableNukes(): boolean {
+ return this._gameConfig.disableNukes;
+ }
bots(): number {
return this._gameConfig.bots;
}
diff --git a/src/core/execution/FakeHumanExecution.ts b/src/core/execution/FakeHumanExecution.ts
index 41122e374..87a5eea29 100644
--- a/src/core/execution/FakeHumanExecution.ts
+++ b/src/core/execution/FakeHumanExecution.ts
@@ -358,12 +358,14 @@ export class FakeHumanExecution implements Execution {
if (this.maybeSpawnWarship()) {
return;
}
- this.maybeSpawnStructure(
- UnitType.MissileSilo,
- 1,
- (t) =>
- new ConstructionExecution(this.player.id(), t, UnitType.MissileSilo),
- );
+ if (!this.mg.config().disableNukes()) {
+ this.maybeSpawnStructure(
+ UnitType.MissileSilo,
+ 1,
+ (t) =>
+ new ConstructionExecution(this.player.id(), t, UnitType.MissileSilo),
+ );
+ }
}
private maybeSpawnStructure(
diff --git a/src/core/game/PlayerImpl.ts b/src/core/game/PlayerImpl.ts
index c1dd2aba4..162e3c681 100644
--- a/src/core/game/PlayerImpl.ts
+++ b/src/core/game/PlayerImpl.ts
@@ -673,6 +673,21 @@ export class PlayerImpl implements Player {
}
canBuild(unitType: UnitType, targetTile: TileRef): TileRef | false {
+ // prevent the building of nukes and nuke related buildings
+ if (this.mg.config().disableNukes()) {
+ if (
+ unitType === UnitType.MissileSilo ||
+ unitType === UnitType.MIRV ||
+ unitType === UnitType.AtomBomb ||
+ unitType === UnitType.HydrogenBomb ||
+ unitType === UnitType.SAMLauncher ||
+ unitType === UnitType.SAMMissile ||
+ unitType === UnitType.MIRVWarhead
+ ) {
+ return false;
+ }
+ }
+
const cost = this.mg.unitInfo(unitType).cost(this);
if (!this.isAlive() || this.gold() < cost) {
return false;
diff --git a/src/server/GameManager.ts b/src/server/GameManager.ts
index ae4446dd3..08049c22a 100644
--- a/src/server/GameManager.ts
+++ b/src/server/GameManager.ts
@@ -34,6 +34,7 @@ export class GameManager {
gameType: GameType.Private,
difficulty: Difficulty.Medium,
disableNPCs: false,
+ disableNukes: false,
infiniteGold: false,
infiniteTroops: false,
instantBuild: false,
diff --git a/src/server/GameServer.ts b/src/server/GameServer.ts
index f60a63efd..2663186c7 100644
--- a/src/server/GameServer.ts
+++ b/src/server/GameServer.ts
@@ -71,6 +71,9 @@ export class GameServer {
if (gameConfig.disableNPCs != null) {
this.gameConfig.disableNPCs = gameConfig.disableNPCs;
}
+ if (gameConfig.disableNukes != null) {
+ this.gameConfig.disableNukes = gameConfig.disableNukes;
+ }
if (gameConfig.bots != null) {
this.gameConfig.bots = gameConfig.bots;
}
diff --git a/src/server/Master.ts b/src/server/Master.ts
index 9c3d4be6f..829636d6c 100644
--- a/src/server/Master.ts
+++ b/src/server/Master.ts
@@ -233,6 +233,7 @@ async function schedulePublicGame() {
infiniteTroops: false,
instantBuild: false,
disableNPCs: false,
+ disableNukes: false,
bots: 400,
} as GameConfig;
diff --git a/src/server/Worker.ts b/src/server/Worker.ts
index 02fc58ad9..d4def7141 100644
--- a/src/server/Worker.ts
+++ b/src/server/Worker.ts
@@ -164,6 +164,7 @@ export function startWorker() {
instantBuild: req.body.instantBuild,
bots: req.body.bots,
disableNPCs: req.body.disableNPCs,
+ disableNukes: req.body.disableNukes,
});
res.status(200).json({ success: true });
}),