diff --git a/src/core/execution/TransportShipExecution.ts b/src/core/execution/TransportShipExecution.ts index a54a040c0..6e37e066d 100644 --- a/src/core/execution/TransportShipExecution.ts +++ b/src/core/execution/TransportShipExecution.ts @@ -1,3 +1,4 @@ +import { renderTroops } from "../../client/Utils"; import { Execution, Game, @@ -14,6 +15,7 @@ import { PathFindResultType } from "../pathfinding/AStar"; import { PathFinder } from "../pathfinding/PathFinding"; import { AttackExecution } from "./AttackExecution"; +const malusForRetreat = 25; export class TransportShipExecution implements Execution { private lastMove: number; @@ -222,14 +224,23 @@ export class TransportShipExecution implements Execution { switch (result.type) { case PathFindResultType.Completed: if (this.mg.owner(this.dst) === this.attacker) { - this.attacker.addTroops(this.boat.troops()); + const deaths = this.boat.troops() * (malusForRetreat / 100); + const survivors = this.boat.troops() - deaths; + this.attacker.addTroops(survivors); this.boat.delete(false); this.active = false; // Record stats this.mg .stats() - .boatArriveTroops(this.attacker, this.target, this.boat.troops()); + .boatArriveTroops(this.attacker, this.target, survivors); + if (deaths) { + this.mg.displayMessage( + `Attack cancelled, ${renderTroops(deaths)} soldiers killed during retreat.`, + MessageType.ATTACK_CANCELLED, + this.attacker.id(), + ); + } return; } this.attacker.conquer(this.dst); diff --git a/tests/Attack.test.ts b/tests/Attack.test.ts index 78f4928e7..fceeb365a 100644 --- a/tests/Attack.test.ts +++ b/tests/Attack.test.ts @@ -111,6 +111,26 @@ describe("Attack", () => { expect(nuke.isActive()).toBe(false); expect(defender.units(UnitType.TransportShip)[0].troops()).toBeLessThan(90); }); + + test("Boat penalty on retreat Transport Ship arrival", async () => { + const player_start_troops = defender.troops(); + const boat_troops = player_start_troops * 0.5; + + sendBoat(game.ref(15, 8), game.ref(10, 5), boat_troops); + + game.executeNextTick(); + + const ship = defender.units(UnitType.TransportShip)[0]; + expect(ship.troops()).toBe(boat_troops); + expect(ship.isActive()).toBe(true); + + ship.orderBoatRetreat(); + game.executeNextTick(); + + expect(ship.isActive()).toBe(false); + expect(boat_troops).toBeLessThan(defender.troops()); + expect(defender.troops()).toBeLessThan(player_start_troops); + }); }); let playerA: Player;