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 }); }),