From 3013133d0882ac7503d22ec8edbdd2cb8d36e9e3 Mon Sep 17 00:00:00 2001
From: FloPinguin <25036848+FloPinguin@users.noreply.github.com>
Date: Thu, 12 Mar 2026 04:39:39 +0100
Subject: [PATCH] =?UTF-8?q?Embrace=20the=20aftergame!=20=F0=9F=98=84=20(#3?=
=?UTF-8?q?410)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## Description:
In v30 we have the following change to prevent teammates from destroying
your structures:
**Block nuking teammate structures** - Nukes blocked if they'd hit a
teammate's structure (that was possible by nuking oceans / rivers) (by
@FloPinguin)
Original idea was from Wonder.
I think it makes sense, but it has a side effect: The aftergame, which
many players love, will be dead because of this change.
I think a lot of complaints will follow after v30 is live.
So why not add a little bit of logic for the aftergame?
After a team wins/loses, players can nuke their teammates. No longer
need to aim for water. SAMs also intercept teammate nukes in this phase.
## 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
---
src/core/execution/SAMLauncherExecution.ts | 33 +++++++++++++++++-----
src/core/game/PlayerImpl.ts | 10 +++++--
2 files changed, 33 insertions(+), 10 deletions(-)
diff --git a/src/core/execution/SAMLauncherExecution.ts b/src/core/execution/SAMLauncherExecution.ts
index 2e1682abb..7d8faefff 100644
--- a/src/core/execution/SAMLauncherExecution.ts
+++ b/src/core/execution/SAMLauncherExecution.ts
@@ -116,12 +116,20 @@ class SAMTargetingSystem {
detectionRange,
[UnitType.AtomBomb, UnitType.HydrogenBomb],
({ unit }) => {
- return (
- isUnit(unit) &&
- unit.owner() !== this.sam.owner() &&
- !this.sam.owner().isFriendly(unit.owner()) &&
- !unit.targetedBySAM()
- );
+ if (!isUnit(unit) || unit.targetedBySAM()) return false;
+ if (unit.owner() === this.sam.owner()) return false;
+
+ const samOwner = this.sam.owner();
+ const nukeOwner = unit.owner();
+
+ // After game-over in team games, SAMs also target teammate nukes (aftergame fun)
+ if (samOwner.isFriendly(nukeOwner)) {
+ return (
+ this.mg.getWinner() !== null && samOwner.isOnSameTeam(nukeOwner)
+ );
+ }
+
+ return true;
},
);
@@ -271,7 +279,18 @@ export class SAMLauncherExecution implements Execution {
({ unit }) => {
if (!isUnit(unit)) return false;
if (unit.owner() === this.player) return false;
- if (this.player.isFriendly(unit.owner())) return false;
+
+ // After game-over in team games, SAMs also target teammate MIRVs (aftergame fun)
+ const nukeOwner = unit.owner();
+ if (this.player.isFriendly(nukeOwner)) {
+ if (
+ this.mg.getWinner() === null ||
+ !this.player.isOnSameTeam(nukeOwner)
+ ) {
+ return false;
+ }
+ }
+
const dst = unit.targetTile();
return (
this.sam !== null &&
diff --git a/src/core/game/PlayerImpl.ts b/src/core/game/PlayerImpl.ts
index 975d5a70f..f8c5b88cb 100644
--- a/src/core/game/PlayerImpl.ts
+++ b/src/core/game/PlayerImpl.ts
@@ -1180,16 +1180,20 @@ export class PlayerImpl implements Player {
return false;
}
const owner = this.mg.owner(tile);
+ // Allow nuking teammates after the game is over (aftergame fun)
+ const gameOver = this.mg.getWinner() !== null;
if (owner.isPlayer()) {
- if (this.isOnSameTeam(owner)) {
+ if (this.isOnSameTeam(owner) && !gameOver) {
return false;
}
}
- // Prevent launching nukes that would hit teammate structures (only in team games)
+ // Prevent launching nukes that would hit teammate structures (only in team games).
+ // Disabled after game-over so players can nuke teammates in the aftergame.
if (
this.mg.config().gameConfig().gameMode === GameMode.Team &&
- nukeType !== UnitType.MIRV
+ nukeType !== UnitType.MIRV &&
+ !gameOver
) {
const magnitude = this.mg.config().nukeMagnitudes(nukeType);
const wouldHitTeammate = this.mg.anyUnitNearby(