mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 10:53:31 +00:00
parity
This commit is contained in:
@@ -32,7 +32,7 @@ interface TeamEntry {
|
||||
totalWarShips: string;
|
||||
totalCities: string;
|
||||
totalScoreSort: number;
|
||||
crownTicks: number;
|
||||
crownSeconds: number;
|
||||
players: PlayerView[];
|
||||
}
|
||||
|
||||
@@ -168,7 +168,11 @@ export class TeamStats extends LitElement implements Layer {
|
||||
0,
|
||||
currentTick - this.game.config().numSpawnPhaseTurns(),
|
||||
);
|
||||
const elapsedSeconds = Math.floor(elapsedGameTicks / 10);
|
||||
const maxTimerValue = this.game.config().gameConfig().maxTimerValue;
|
||||
const elapsedSeconds =
|
||||
maxTimerValue !== undefined
|
||||
? Math.min(Math.floor(elapsedGameTicks / 10), maxTimerValue * 60)
|
||||
: Math.floor(elapsedGameTicks / 10);
|
||||
const serverCrownTicks = this.game.teamCrownTicks() ?? {};
|
||||
// Crown holder = team with most tiles (same logic as WinCheckExecution)
|
||||
let crownHolder: string | null = null;
|
||||
@@ -237,7 +241,11 @@ export class TeamStats extends LitElement implements Layer {
|
||||
totalGold: renderNumber(totalGold),
|
||||
totalMaxTroops: renderTroops(totalMaxTroops),
|
||||
players: teamPlayers,
|
||||
crownTicks: normalizedCrownTicks.get(teamStr) ?? 0,
|
||||
crownSeconds:
|
||||
this._gameOver && this.game.competitiveScores()
|
||||
? (this.game.competitiveScores()!.find((s) => s.team === teamStr)
|
||||
?.crownTimeSeconds ?? 0)
|
||||
: Math.floor((normalizedCrownTicks.get(teamStr) ?? 0) / 10),
|
||||
|
||||
totalLaunchers: renderNumber(totalLaunchers),
|
||||
totalSAMs: renderNumber(totalSAMs),
|
||||
@@ -335,8 +343,7 @@ export class TeamStats extends LitElement implements Layer {
|
||||
return html`
|
||||
<div class="${rowClass}">
|
||||
${td(team.teamName)} ${td(team.totalScoreStr)}
|
||||
${td(team.peakScoreStr)}
|
||||
${td(secondsToHms(Math.floor(team.crownTicks / 10)))}
|
||||
${td(team.peakScoreStr)} ${td(secondsToHms(team.crownSeconds))}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
} from "../../../client/Utils";
|
||||
import { ColorPalette, Pattern } from "../../../core/CosmeticSchemas";
|
||||
import { EventBus } from "../../../core/EventBus";
|
||||
import { TeamScoreBreakdown } from "../../../core/game/CompetitiveScoring";
|
||||
import { RankedType } from "../../../core/game/Game";
|
||||
import { GameUpdateType } from "../../../core/game/GameUpdates";
|
||||
import { GameView } from "../../../core/game/GameView";
|
||||
@@ -46,8 +45,9 @@ export class WinModal extends LitElement implements Layer {
|
||||
@state()
|
||||
private patternContent: TemplateResult | null = null;
|
||||
|
||||
@state()
|
||||
private competitiveScores: TeamScoreBreakdown[] | null = null;
|
||||
private get competitiveScores() {
|
||||
return this.game.competitiveScores();
|
||||
}
|
||||
|
||||
private _title: string;
|
||||
|
||||
@@ -409,9 +409,6 @@ export class WinModal extends LitElement implements Layer {
|
||||
// ...
|
||||
} else if (wu.winner[0] === "team") {
|
||||
this.eventBus.emit(new SendWinnerEvent(wu.winner, wu.allPlayersStats));
|
||||
if (wu.competitiveScores) {
|
||||
this.competitiveScores = wu.competitiveScores;
|
||||
}
|
||||
if (wu.winner[1] === this.game.myPlayer()?.team()) {
|
||||
this._title = translateText("win_modal.your_team");
|
||||
this.isWin = true;
|
||||
|
||||
@@ -22,6 +22,14 @@ export class TeamMetricsExecution implements Execution {
|
||||
if (ticks % 10 !== 0) return;
|
||||
if (this.mg === null) throw new Error("Not initialized");
|
||||
|
||||
// Stop tracking after the game timer expires.
|
||||
const maxTimerValue = this.mg.config().gameConfig().maxTimerValue;
|
||||
if (maxTimerValue !== undefined) {
|
||||
const elapsedSeconds =
|
||||
(ticks - this.mg.config().numSpawnPhaseTurns()) / 10;
|
||||
if (elapsedSeconds >= maxTimerValue * 60) return;
|
||||
}
|
||||
|
||||
const teamToTiles = new Map<Team, number>();
|
||||
for (const player of this.mg.players()) {
|
||||
const team = player.team();
|
||||
|
||||
@@ -6,6 +6,7 @@ import { PatternDecoder } from "../PatternDecoder";
|
||||
import { ClientID, GameID, Player, PlayerCosmetics } from "../Schemas";
|
||||
import { createRandomName } from "../Util";
|
||||
import { WorkerClient } from "../worker/WorkerClient";
|
||||
import { TeamScoreBreakdown } from "./CompetitiveScoring";
|
||||
import {
|
||||
Cell,
|
||||
EmojiMessage,
|
||||
@@ -33,6 +34,7 @@ import {
|
||||
GameUpdateViewData,
|
||||
PlayerUpdate,
|
||||
UnitUpdate,
|
||||
WinUpdate,
|
||||
} from "./GameUpdates";
|
||||
import { MotionPlanRecord, unpackMotionPlans } from "./MotionPlans";
|
||||
import { TerrainMapData } from "./TerrainMapLoader";
|
||||
@@ -631,6 +633,7 @@ export class GameView implements GameMap {
|
||||
private trainUnitToEngine = new Map<number, number>();
|
||||
|
||||
private toDelete = new Set<number>();
|
||||
private _competitiveScores: TeamScoreBreakdown[] | null = null;
|
||||
|
||||
private _cosmetics: Map<string, PlayerCosmetics> = new Map();
|
||||
|
||||
@@ -679,6 +682,11 @@ export class GameView implements GameMap {
|
||||
return this.lastUpdate?.teamCrownTicks;
|
||||
}
|
||||
|
||||
/** Competitive scores set once at game end (authoritative). */
|
||||
public competitiveScores(): TeamScoreBreakdown[] | null {
|
||||
return this._competitiveScores;
|
||||
}
|
||||
|
||||
public motionPlans(): ReadonlyMap<
|
||||
number,
|
||||
{
|
||||
@@ -803,6 +811,17 @@ export class GameView implements GameMap {
|
||||
}
|
||||
});
|
||||
|
||||
// Capture competitive scores from WinUpdate (once)
|
||||
if (this._competitiveScores === null && gu.updates) {
|
||||
const winUpdates = gu.updates[GameUpdateType.Win] as WinUpdate[];
|
||||
for (const wu of winUpdates) {
|
||||
if (wu.competitiveScores) {
|
||||
this._competitiveScores = wu.competitiveScores;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.advanceMotionPlannedUnits(gu.tick);
|
||||
this.rebuildMotionPlannedUnitIdsCacheIfDirty();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user