Show max troops in PlayerInfoOverlay and leaderboard 🖌️ (#2625)

## Description:

In the main discord, people seem to be divided in their opinions about
this.
But lets see what the playtest-people are saying, we can easily roll
this back.

<img width="197" height="312" alt="Screenshot 2025-12-15 220648"
src="https://github.com/user-attachments/assets/c6acd1f8-03b1-4949-b15e-6a32f8460e18"
/>
<img width="405" height="323" alt="Screenshot 2025-12-15 220623"
src="https://github.com/user-attachments/assets/21190a6f-1a0b-4db3-b6d0-c0722e98902a"
/>

## 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:
FloPinguin
This commit is contained in:
FloPinguin
2025-12-16 05:22:59 +01:00
committed by GitHub
parent 58c7cdd46f
commit f96fd6dc12
3 changed files with 37 additions and 20 deletions
+2 -1
View File
@@ -557,7 +557,7 @@
"team": "Team",
"owned": "Owned",
"gold": "Gold",
"troops": "Troops",
"maxtroops": "Max troops",
"launchers": "Launchers",
"sams": "SAMs",
"warships": "Warships",
@@ -573,6 +573,7 @@
"team": "Team",
"alliance_timeout": "Alliance ends in",
"troops": "Troops",
"maxtroops": "Max troops",
"a_troops": "Attacking troops",
"gold": "Gold",
"ports": "Ports",
+23 -19
View File
@@ -1,7 +1,7 @@
import { LitElement, html } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { repeat } from "lit/directives/repeat.js";
import { translateText } from "../../../client/Utils";
import { renderTroops, translateText } from "../../../client/Utils";
import { EventBus, GameEvent } from "../../../core/EventBus";
import { GameView, PlayerView, UnitView } from "../../../core/game/GameView";
import { renderNumber } from "../../Utils";
@@ -12,7 +12,7 @@ interface Entry {
position: number;
score: string;
gold: string;
troops: string;
maxTroops: string;
isMyPlayer: boolean;
isOnSameTeam: boolean;
player: PlayerView;
@@ -44,7 +44,7 @@ export class Leaderboard extends LitElement implements Layer {
private showTopFive = true;
@state()
private _sortKey: "tiles" | "gold" | "troops" = "tiles";
private _sortKey: "tiles" | "gold" | "maxtroops" = "tiles";
@state()
private _sortOrder: "asc" | "desc" = "desc";
@@ -63,7 +63,7 @@ export class Leaderboard extends LitElement implements Layer {
}
}
private setSort(key: "tiles" | "gold" | "troops") {
private setSort(key: "tiles" | "gold" | "maxtroops") {
if (this._sortKey === key) {
this._sortOrder = this._sortOrder === "asc" ? "desc" : "asc";
} else {
@@ -82,14 +82,16 @@ export class Leaderboard extends LitElement implements Layer {
const compare = (a: number, b: number) =>
this._sortOrder === "asc" ? a - b : b - a;
const maxTroops = (p: PlayerView) => this.game!.config().maxTroops(p);
switch (this._sortKey) {
case "gold":
sorted = sorted.sort((a, b) =>
compare(Number(a.gold()), Number(b.gold())),
);
break;
case "troops":
sorted = sorted.sort((a, b) => compare(a.troops(), b.troops()));
case "maxtroops":
sorted = sorted.sort((a, b) => compare(maxTroops(a), maxTroops(b)));
break;
default:
sorted = sorted.sort((a, b) =>
@@ -106,7 +108,7 @@ export class Leaderboard extends LitElement implements Layer {
: alivePlayers;
this.players = playersToShow.map((player, index) => {
const troops = player.troops() / 10;
const maxTroops = this.game!.config().maxTroops(player);
return {
name: player.displayName(),
position: index + 1,
@@ -114,7 +116,7 @@ export class Leaderboard extends LitElement implements Layer {
player.numTilesOwned() / numTilesWithoutFallout,
),
gold: renderNumber(player.gold()),
troops: renderNumber(troops),
maxTroops: renderTroops(maxTroops),
isMyPlayer: player === myPlayer,
isOnSameTeam:
myPlayer !== null &&
@@ -136,7 +138,7 @@ export class Leaderboard extends LitElement implements Layer {
}
if (myPlayer.isAlive()) {
const myPlayerTroops = myPlayer.troops() / 10;
const myPlayerMaxTroops = this.game!.config().maxTroops(myPlayer);
this.players.pop();
this.players.push({
name: myPlayer.displayName(),
@@ -145,7 +147,7 @@ export class Leaderboard extends LitElement implements Layer {
myPlayer.numTilesOwned() / this.game.numLandTiles(),
),
gold: renderNumber(myPlayer.gold()),
troops: renderNumber(myPlayerTroops),
maxTroops: renderTroops(myPlayerMaxTroops),
isMyPlayer: true,
isOnSameTeam: true,
player: myPlayer,
@@ -181,17 +183,19 @@ export class Leaderboard extends LitElement implements Layer {
>
<div
class="grid bg-gray-800/70 w-full text-xs md:text-xs lg:text-sm"
style="grid-template-columns: 30px 100px 70px 55px 75px;"
style="grid-template-columns: 30px 100px 70px 55px 105px;"
>
<div class="contents font-bold bg-gray-700/50">
<div class="py-1 md:py-2 text-center border-b border-slate-500">
#
</div>
<div class="py-1 md:py-2 text-center border-b border-slate-500">
<div
class="py-1 md:py-2 text-center border-b border-slate-500 truncate"
>
${translateText("leaderboard.player")}
</div>
<div
class="py-1 md:py-2 text-center border-b border-slate-500 cursor-pointer whitespace-nowrap"
class="py-1 md:py-2 text-center border-b border-slate-500 cursor-pointer whitespace-nowrap truncate"
@click=${() => this.setSort("tiles")}
>
${translateText("leaderboard.owned")}
@@ -202,7 +206,7 @@ export class Leaderboard extends LitElement implements Layer {
: ""}
</div>
<div
class="py-1 md:py-2 text-center border-b border-slate-500 cursor-pointer whitespace-nowrap"
class="py-1 md:py-2 text-center border-b border-slate-500 cursor-pointer whitespace-nowrap truncate"
@click=${() => this.setSort("gold")}
>
${translateText("leaderboard.gold")}
@@ -213,11 +217,11 @@ export class Leaderboard extends LitElement implements Layer {
: ""}
</div>
<div
class="py-1 md:py-2 text-center border-b border-slate-500 cursor-pointer whitespace-nowrap"
@click=${() => this.setSort("troops")}
class="py-1 md:py-2 text-center border-b border-slate-500 cursor-pointer whitespace-nowrap truncate"
@click=${() => this.setSort("maxtroops")}
>
${translateText("leaderboard.troops")}
${this._sortKey === "troops"
${translateText("leaderboard.maxtroops")}
${this._sortKey === "maxtroops"
? this._sortOrder === "asc"
? "⬆️"
: "⬇️"
@@ -250,7 +254,7 @@ export class Leaderboard extends LitElement implements Layer {
${player.gold}
</div>
<div class="py-1 md:py-2 text-center border-b border-slate-500">
${player.troops}
${player.maxTroops}
</div>
</div>
`,
@@ -254,6 +254,7 @@ export class PlayerInfoOverlay extends LitElement implements Layer {
const isFriendly = myPlayer?.isFriendly(player);
const isAllied = myPlayer?.isAlliedWith(player);
let relationHtml: TemplateResult | null = null;
const maxTroops = this.game.config().maxTroops(player);
const attackingTroops = player
.outgoingAttacks()
.map((a) => a.troops)
@@ -359,6 +360,17 @@ export class PlayerInfoOverlay extends LitElement implements Layer {
</span>
</div>`
: ""}
${maxTroops >= 1
? html`<div
class="flex gap-2 text-sm opacity-80"
translate="no"
>
${translateText("player_info_overlay.maxtroops")}
<span class="ml-auto mr-0 font-bold">
${renderTroops(maxTroops)}
</span>
</div>`
: ""}
${attackingTroops >= 1
? html`<div
class="flex gap-2 text-sm opacity-80"