Have MIRV damage asymptote to 5% of total population (#1570)

## Description:

Decreasing MIRV warhead blast radius nerfed them too much, so have them
destroy 95% of population.

## 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
- [x] I have read and accepted the CLA aggreement (only required once).

## Please put your Discord username so you can be contacted if a bug or
regression is found:

evan
This commit is contained in:
evanpelle
2025-07-25 15:44:32 -07:00
committed by GitHub
parent 65937b7e69
commit 932d4f3be2
3 changed files with 52 additions and 8 deletions
+8 -2
View File
@@ -1,6 +1,5 @@
import { Colord } from "colord";
import { JWK } from "jose";
import { GameConfig, GameID, TeamCountConfig } from "../Schemas";
import {
Difficulty,
Game,
@@ -18,6 +17,8 @@ import {
import { GameMap, TileRef } from "../game/GameMap";
import { PlayerView } from "../game/GameView";
import { UserSettings } from "../game/UserSettings";
import { GameConfig, GameID, TeamCountConfig } from "../Schemas";
import { NukeType } from "../StatsSchemas";
export enum GameEnv {
Dev,
@@ -157,7 +158,12 @@ export interface Config {
defaultNukeSpeed(): number;
defaultNukeTargetableRange(): number;
defaultSamRange(): number;
nukeDeathFactor(humans: number, tilesOwned: number): number;
nukeDeathFactor(
nukeType: NukeType,
humans: number,
tilesOwned: number,
maxPop: number,
): number;
structureMinDist(): number;
isReplay(): boolean;
allianceExtensionPromptOffset(): number;
+16 -2
View File
@@ -23,6 +23,7 @@ import { TileRef } from "../game/GameMap";
import { PlayerView } from "../game/GameView";
import { UserSettings } from "../game/UserSettings";
import { GameConfig, GameID, TeamCountConfig } from "../Schemas";
import { NukeType } from "../StatsSchemas";
import { assertNever, simpleHash, within } from "../Util";
import { Config, GameEnv, NukeMagnitude, ServerConfig, Theme } from "./Config";
import { PastelTheme } from "./PastelTheme";
@@ -822,8 +823,21 @@ export class DefaultConfig implements Config {
}
// Humans can be population, soldiers attacking, soldiers in boat etc.
nukeDeathFactor(humans: number, tilesOwned: number): number {
return (5 * humans) / Math.max(1, tilesOwned);
nukeDeathFactor(
nukeType: NukeType,
humans: number,
tilesOwned: number,
maxPop: number,
): number {
if (nukeType !== UnitType.MIRVWarhead) {
return (5 * humans) / Math.max(1, tilesOwned);
}
const targetPop = 0.05 * maxPop;
const excessPop = Math.max(0, humans - targetPop);
const scalingFactor = 20000;
return (scalingFactor * excessPop * excessPop) / (maxPop * maxPop);
}
structureMinDist(): number {
+28 -4
View File
@@ -203,6 +203,10 @@ export class NukeExecution implements Execution {
const toDestroy = this.tilesToDestroy();
this.maybeBreakAlliances(toDestroy);
const maxPop = this.target().isPlayer()
? this.mg.config().maxPopulation(this.target() as Player)
: 1;
for (const tile of toDestroy) {
const owner = this.mg.owner(tile);
if (owner.isPlayer()) {
@@ -210,25 +214,45 @@ export class NukeExecution implements Execution {
owner.removeTroops(
this.mg
.config()
.nukeDeathFactor(owner.troops(), owner.numTilesOwned()),
.nukeDeathFactor(
this.nukeType,
owner.troops(),
owner.numTilesOwned(),
maxPop,
),
);
owner.removeWorkers(
this.mg
.config()
.nukeDeathFactor(owner.workers(), owner.numTilesOwned()),
.nukeDeathFactor(
this.nukeType,
owner.workers(),
owner.numTilesOwned(),
maxPop,
),
);
owner.outgoingAttacks().forEach((attack) => {
const deaths =
this.mg
?.config()
.nukeDeathFactor(attack.troops(), owner.numTilesOwned()) ?? 0;
.nukeDeathFactor(
this.nukeType,
attack.troops(),
owner.numTilesOwned(),
maxPop,
) ?? 0;
attack.setTroops(attack.troops() - deaths);
});
owner.units(UnitType.TransportShip).forEach((attack) => {
const deaths =
this.mg
?.config()
.nukeDeathFactor(attack.troops(), owner.numTilesOwned()) ?? 0;
.nukeDeathFactor(
this.nukeType,
attack.troops(),
owner.numTilesOwned(),
maxPop,
) ?? 0;
attack.setTroops(attack.troops() - deaths);
});
}