mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-26 15:54:37 +00:00
Fix transport ship's troop count to update when a hydro hits the player. (#4381)
**Add approved & assigned issue number here:** Resolves #4308 ## Description: When nuclear damage reduces a player's troop count, it also affects any transports ships in the water. This works well and is useful to avoid exploiting tranports to avoid hydro damages. `UnitImpl.setTroops()` changes the transports troop count without queuing a unit update. the core value changes, but the client never receives a fresh UnitUpdate unless something else touches the ship. - UnitImpl.ts now emits a UnitUpdate when a unit troop count actually changes. - NukeExecution.ts batches transport ship nuke losses, then applies one final troop update per ship. - Attack.test.ts now asserts the nuke tick includes a transport UnitUpdate with the reduced troop count. ## Please complete the following: - [N/A] I have added screenshots for all UI updates - [N/A] 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 ## Please put your Discord username so you can be contacted if a bug or regression is found: elliotlepley
This commit is contained in:
@@ -375,6 +375,10 @@ export class NukeExecution implements Execution {
|
||||
for (const [player, numImpactedTiles] of tilesPerPlayers) {
|
||||
const tilesBeforeNuke = player.numTilesOwned() + numImpactedTiles;
|
||||
const transportShips = player.units(UnitType.TransportShip);
|
||||
const transportShipTroops = new Map<Unit, number>();
|
||||
for (const unit of transportShips) {
|
||||
transportShipTroops.set(unit, unit.troops());
|
||||
}
|
||||
const outgoingAttacks = player.outgoingAttacks();
|
||||
const maxTroops = config.maxTroops(player);
|
||||
// nukeDeathFactor could compute the complete fallout in a single call instead
|
||||
@@ -400,16 +404,19 @@ export class NukeExecution implements Execution {
|
||||
attack.setTroops(attackTroops - deaths);
|
||||
}
|
||||
for (const unit of transportShips) {
|
||||
const unitTroops = unit.troops();
|
||||
const unitTroops = transportShipTroops.get(unit) ?? unit.troops();
|
||||
const deaths = config.nukeDeathFactor(
|
||||
this.nukeType,
|
||||
unitTroops,
|
||||
numTilesLeft,
|
||||
maxTroops,
|
||||
);
|
||||
unit.setTroops(unitTroops - deaths);
|
||||
transportShipTroops.set(unit, Math.max(0, unitTroops - deaths));
|
||||
}
|
||||
}
|
||||
for (const [unit, troops] of transportShipTroops) {
|
||||
unit.setTroops(troops);
|
||||
}
|
||||
}
|
||||
|
||||
const outer2 = magnitude.outer * magnitude.outer;
|
||||
|
||||
@@ -172,7 +172,12 @@ export class UnitImpl implements Unit {
|
||||
}
|
||||
|
||||
setTroops(troops: number): void {
|
||||
this._troops = Math.max(0, troops);
|
||||
const nextTroops = Math.max(0, troops);
|
||||
if (this._troops === nextTroops) {
|
||||
return;
|
||||
}
|
||||
this._troops = nextTroops;
|
||||
this.mg.addUpdate(this.toUpdate());
|
||||
}
|
||||
troops(): number {
|
||||
return this._troops;
|
||||
|
||||
+17
-2
@@ -9,6 +9,7 @@ import {
|
||||
UnitType,
|
||||
} from "../src/core/game/Game";
|
||||
import { TileRef } from "../src/core/game/GameMap";
|
||||
import { GameUpdateType, UnitUpdate } from "../src/core/game/GameUpdates";
|
||||
import { GameID } from "../src/core/Schemas";
|
||||
import { setup } from "./util/Setup";
|
||||
import { TestConfig } from "./util/TestConfig";
|
||||
@@ -119,10 +120,24 @@ describe("Attack", () => {
|
||||
const ship = defender.units(UnitType.TransportShip)[0];
|
||||
expect(ship.troops()).toBe(100);
|
||||
|
||||
game.executeNextTick();
|
||||
const updates = game.executeNextTick();
|
||||
const updatedShip = defender.units(UnitType.TransportShip)[0];
|
||||
const shipUpdates = (updates[GameUpdateType.Unit] as UnitUpdate[]).filter(
|
||||
(u) => u.id === ship.id(),
|
||||
);
|
||||
|
||||
expect(nuke.isActive()).toBe(false);
|
||||
expect(defender.units(UnitType.TransportShip)[0].troops()).toBeLessThan(90);
|
||||
expect(updatedShip.troops()).toBeLessThan(90);
|
||||
expect(shipUpdates).toContainEqual(
|
||||
expect.objectContaining({
|
||||
id: ship.id(),
|
||||
unitType: UnitType.TransportShip,
|
||||
troops: updatedShip.troops(),
|
||||
transportShipState: expect.objectContaining({
|
||||
troops: updatedShip.troops(),
|
||||
}),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test("Boat penalty on retreat Transport Ship arrival", async () => {
|
||||
|
||||
Reference in New Issue
Block a user