From 904425cab0df60a3d0dc68aa49d439aefa93b5e1 Mon Sep 17 00:00:00 2001 From: FloPinguin <25036848+FloPinguin@users.noreply.github.com> Date: Wed, 4 Feb 2026 12:38:49 +0100 Subject: [PATCH] =?UTF-8?q?Prevent=20players=20from=20nuking=20their=20tea?= =?UTF-8?q?mmates=20structures=20=F0=9F=92=A5=20(#3105)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description: It is possible to hit your teammates while throwing a nuke onto water or enemies. This PR blocks the nuking entirely if you would hit a teammates structure. Because they are valuable. Feature requested by Wonder :) https://github.com/user-attachments/assets/448a3444-cc3d-4e76-acaf-595decab1634 ## 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 --------- Co-authored-by: Ryan <7389646+ryanbarlow97@users.noreply.github.com> --- src/core/game/PlayerImpl.ts | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/core/game/PlayerImpl.ts b/src/core/game/PlayerImpl.ts index fae23df8e..64cdf70c8 100644 --- a/src/core/game/PlayerImpl.ts +++ b/src/core/game/PlayerImpl.ts @@ -20,6 +20,7 @@ import { ColoredTeams, Embargo, EmojiMessage, + GameMode, Gold, MessageType, MutableAlliance, @@ -29,6 +30,7 @@ import { PlayerProfile, PlayerType, Relation, + StructureTypes, Team, TerraNullius, Tick, @@ -994,10 +996,10 @@ export class PlayerImpl implements Player { if (!this.mg.hasOwner(targetTile)) { return false; } - return this.nukeSpawn(targetTile); + return this.nukeSpawn(targetTile, unitType); case UnitType.AtomBomb: case UnitType.HydrogenBomb: - return this.nukeSpawn(targetTile); + return this.nukeSpawn(targetTile, unitType); case UnitType.MIRVWarhead: return targetTile; case UnitType.Port: @@ -1024,7 +1026,7 @@ export class PlayerImpl implements Player { } } - nukeSpawn(tile: TileRef): TileRef | false { + nukeSpawn(tile: TileRef, nukeType: UnitType): TileRef | false { if (this.mg.isSpawnImmunityActive()) { return false; } @@ -1034,6 +1036,24 @@ export class PlayerImpl implements Player { return false; } } + + // Prevent launching nukes that would hit teammate structures (only in team games) + if ( + this.mg.config().gameConfig().gameMode === GameMode.Team && + nukeType !== UnitType.MIRV + ) { + const magnitude = this.mg.config().nukeMagnitudes(nukeType); + const wouldHitTeammate = this.mg.anyUnitNearby( + tile, + magnitude.outer, + StructureTypes, + (unit) => unit.owner().isPlayer() && this.isOnSameTeam(unit.owner()), + ); + if (wouldHitTeammate) { + return false; + } + } + // only get missilesilos that are not on cooldown and not under construction const spawns = this.units(UnitType.MissileSilo) .filter((silo) => {