From d9ea9fd432f936d4122971a38c664d38c8938e2a Mon Sep 17 00:00:00 2001
From: VariableVince <24507472+VariableVince@users.noreply.github.com>
Date: Fri, 31 Oct 2025 19:31:18 +0100
Subject: [PATCH] Fix betrayals for Nations always 0 on Player Info Panel
(#2334)
## Description:
Betrayal count in PlayerUpdates came from stats. But stats are only kept
for players with ClientID aka real humans. So betrayals stayed 0 for
Nations even after betraying others. This PR fixes it by keeping a
seperate betrayal count for PlayerUpdates while stats are still being
kept to go in the database.
See bug report
https://discord.com/channels/1284581928254701718/1432759837560799403
After:
## 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:
tryout33
---
src/core/game/Game.ts | 1 +
src/core/game/GameUpdates.ts | 2 +-
src/core/game/PlayerImpl.ts | 11 ++++++++---
src/core/game/StatsImpl.ts | 7 ++-----
4 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/src/core/game/Game.ts b/src/core/game/Game.ts
index 84fbb9e4b..1631db8a9 100644
--- a/src/core/game/Game.ts
+++ b/src/core/game/Game.ts
@@ -607,6 +607,7 @@ export interface Player {
canSendAllianceRequest(other: Player): boolean;
breakAlliance(alliance: Alliance): void;
createAllianceRequest(recipient: Player): AllianceRequest | null;
+ betrayals(): number;
// Targeting
canTarget(other: Player): boolean;
diff --git a/src/core/game/GameUpdates.ts b/src/core/game/GameUpdates.ts
index 922212923..a4f5e4f92 100644
--- a/src/core/game/GameUpdates.ts
+++ b/src/core/game/GameUpdates.ts
@@ -169,7 +169,7 @@ export interface PlayerUpdate {
outgoingAllianceRequests: PlayerID[];
alliances: AllianceView[];
hasSpawned: boolean;
- betrayals?: bigint;
+ betrayals: number;
lastDeleteUnitTick: Tick;
}
diff --git a/src/core/game/PlayerImpl.ts b/src/core/game/PlayerImpl.ts
index a83c85bfb..7fe3d52f5 100644
--- a/src/core/game/PlayerImpl.ts
+++ b/src/core/game/PlayerImpl.ts
@@ -71,6 +71,7 @@ export class PlayerImpl implements Player {
private _troops: bigint;
markedTraitorTick = -1;
+ private _betrayalCount: number = 0;
private embargoes = new Map();
@@ -123,7 +124,6 @@ export class PlayerImpl implements Player {
const outgoingAllianceRequests = this.outgoingAllianceRequests().map((ar) =>
ar.recipient().id(),
);
- const stats = this.mg.stats().getPlayerStats(this);
return {
type: GameUpdateType.Player,
@@ -174,7 +174,7 @@ export class PlayerImpl implements Player {
}) satisfies AllianceView,
),
hasSpawned: this.hasSpawned(),
- betrayals: stats?.betrayals,
+ betrayals: this._betrayalCount,
lastDeleteUnitTick: this.lastDeleteUnitTick,
};
}
@@ -441,11 +441,16 @@ export class PlayerImpl implements Player {
markTraitor(): void {
this.markedTraitorTick = this.mg.ticks();
+ this._betrayalCount++; // Keep count for FakeHumans too
- // Record stats
+ // Record stats (only for real Humans)
this.mg.stats().betray(this);
}
+ betrayals(): number {
+ return this._betrayalCount;
+ }
+
createAllianceRequest(recipient: Player): AllianceRequest | null {
if (this.isAlliedWith(recipient)) {
throw new Error(`cannot create alliance request, already allies`);
diff --git a/src/core/game/StatsImpl.ts b/src/core/game/StatsImpl.ts
index e3e750897..f6a574848 100644
--- a/src/core/game/StatsImpl.ts
+++ b/src/core/game/StatsImpl.ts
@@ -74,11 +74,8 @@ export class StatsImpl implements Stats {
private _addBetrayal(player: Player, value: BigIntLike) {
const data = this._makePlayerStats(player);
if (data === undefined) return;
- if (data.betrayals === undefined) {
- data.betrayals = _bigint(value);
- } else {
- data.betrayals += _bigint(value);
- }
+ data.betrayals ??= 0n;
+ data.betrayals += _bigint(value);
}
private _addBoat(