Add conquest FX (#1390)

## Description:

Add an animation when the player conquer another one.
The FX consists of two parts: short animation, and the gold won.

It is only displayed to the conquering player, so everybody knows who
won the money if multiple people fighted over the last pixel of a
player.

Changes:
  - Add new update `ConquestUpdate`
  - Add new fx `ConquestFx`
  - Merge conquest logic in `Game`


https://github.com/user-attachments/assets/9f985e41-baa4-48a6-927e-3216274f758c

## 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 understand that submitting code with bugs that could have been
caught through manual testing blocks releases and new features for all
contributors

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

IngloriousTom
This commit is contained in:
DevelopingTom
2025-07-25 19:52:05 -04:00
committed by GitHub
parent 71fe6a81a0
commit c738648460
12 changed files with 126 additions and 34 deletions
+2 -12
View File
@@ -1,4 +1,4 @@
import { renderNumber, renderTroops } from "../../client/Utils";
import { renderTroops } from "../../client/Utils";
import {
Attack,
Execution,
@@ -331,17 +331,7 @@ export class AttackExecution implements Execution {
private handleDeadDefender() {
if (!(this.target.isPlayer() && this.target.numTilesOwned() < 100)) return;
const gold = this.target.gold();
this.mg.displayMessage(
`Conquered ${this.target.displayName()} received ${renderNumber(
gold,
)} gold`,
MessageType.CONQUERED_PLAYER,
this._owner.id(),
gold,
);
this.target.removeGold(gold);
this._owner.addGold(gold);
this.mg.conquerPlayer(this._owner, this.target);
for (let i = 0; i < 10; i++) {
for (const tile of this.target.tiles()) {
+2 -16
View File
@@ -1,6 +1,5 @@
import { renderNumber } from "../../client/Utils";
import { Config } from "../configuration/Config";
import { Execution, Game, MessageType, Player, UnitType } from "../game/Game";
import { Execution, Game, Player, UnitType } from "../game/Game";
import { GameImpl } from "../game/GameImpl";
import { TileRef } from "../game/GameMap";
import { calculateBoundingBox, getMode, inscribed, simpleHash } from "../Util";
@@ -199,20 +198,7 @@ export class PlayerExecution implements Execution {
const tiles = this.mg.bfs(firstTile, filter);
if (this.player.numTilesOwned() === tiles.size) {
const gold = this.player.gold();
this.mg.displayMessage(
`Conquered ${this.player.displayName()} received ${renderNumber(
gold,
)} gold`,
MessageType.CONQUERED_PLAYER,
capturing.id(),
gold,
);
capturing.addGold(gold);
this.player.removeGold(gold);
// Record stats
this.mg.stats().goldWar(capturing, this.player, gold);
this.mg.conquerPlayer(capturing, this.player);
}
for (const tile of tiles) {
+1
View File
@@ -696,6 +696,7 @@ export interface Game extends GameMap {
addUpdate(update: GameUpdate): void;
railNetwork(): RailNetwork;
conquerPlayer(conqueror: Player, conquered: Player);
}
export interface PlayerActions {
+23
View File
@@ -1,3 +1,4 @@
import { renderNumber } from "../../client/Utils";
import { Config } from "../configuration/Config";
import { AllPlayersStats, ClientID, Winner } from "../Schemas";
import { simpleHash } from "../Util";
@@ -875,6 +876,28 @@ export class GameImpl implements Game {
railNetwork(): RailNetwork {
return this._railNetwork;
}
conquerPlayer(conqueror: Player, conquered: Player) {
const gold = conquered.gold();
this.displayMessage(
`Conquered ${conquered.displayName()} received ${renderNumber(
gold,
)} gold`,
MessageType.CONQUERED_PLAYER,
conqueror.id(),
gold,
);
conqueror.addGold(gold);
conquered.removeGold(gold);
this.addUpdate({
type: GameUpdateType.ConquestEvent,
conquerorId: conqueror.id(),
conqueredId: conquered.id(),
gold,
});
// Record stats
this.stats().goldWar(conqueror, conquered, gold);
}
}
// Or a more dynamic approach that will catch new enum values:
+11 -1
View File
@@ -44,6 +44,7 @@ export enum GameUpdateType {
UnitIncoming,
BonusEvent,
RailroadEvent,
ConquestEvent,
}
export type GameUpdate =
@@ -63,7 +64,8 @@ export type GameUpdate =
| UnitIncomingUpdate
| AllianceExtensionUpdate
| BonusEventUpdate
| RailroadUpdate;
| RailroadUpdate
| ConquestUpdate;
export interface BonusEventUpdate {
type: GameUpdateType.BonusEvent;
@@ -86,12 +88,20 @@ export interface RailTile {
tile: TileRef;
railType: RailType;
}
export interface RailroadUpdate {
type: GameUpdateType.RailroadEvent;
isActive: boolean;
railTiles: RailTile[];
}
export interface ConquestUpdate {
type: GameUpdateType.ConquestEvent;
conquerorId: PlayerID;
conqueredId: PlayerID;
gold: Gold;
}
export interface TileUpdateWrapper {
type: GameUpdateType.Tile;
update: TileUpdate;