mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-13 07:15:10 +00:00
feat: Achievement medal overview (#4487)
## Description: In the spirit of achievement hunting, seeing how many medals a player has achieved helps show overall progress. Overview only toggles on when user clicks toggle achievements button. Works on mobile too. https://github.com/user-attachments/assets/ea77075b-5e91-4e62-8ac9-52bcdf95cc64 ## 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 ## Please put your Discord username so you can be contacted if a bug or regression is found: bijx
This commit is contained in:
@@ -1,12 +1,10 @@
|
||||
import { LitElement, html } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators.js";
|
||||
import medalIconRaw from "../../../../resources/images/MedalIconWhite.svg?raw";
|
||||
import { Difficulty, GameMapType } from "../../../core/game/Game";
|
||||
import { terrainMapFileLoader } from "../../TerrainMapFileLoader";
|
||||
import { translateText } from "../../Utils";
|
||||
import { starIcon } from "./MapFavorites";
|
||||
|
||||
const medalMaskUrl = `url('data:image/svg+xml;utf8,${encodeURIComponent(medalIconRaw)}') no-repeat center / contain`;
|
||||
import { MEDAL_ORDER, medalIcon } from "./Medals";
|
||||
|
||||
@customElement("map-display")
|
||||
export class MapDisplay extends LitElement {
|
||||
@@ -177,30 +175,10 @@ export class MapDisplay extends LitElement {
|
||||
}
|
||||
|
||||
private renderMedals() {
|
||||
const medalOrder: Difficulty[] = [
|
||||
Difficulty.Easy,
|
||||
Difficulty.Medium,
|
||||
Difficulty.Hard,
|
||||
Difficulty.Impossible,
|
||||
];
|
||||
const colors: Record<Difficulty, string> = {
|
||||
[Difficulty.Easy]: "var(--medal-easy)",
|
||||
[Difficulty.Medium]: "var(--medal-medium)",
|
||||
[Difficulty.Hard]: "var(--medal-hard)",
|
||||
[Difficulty.Impossible]: "var(--medal-impossible)",
|
||||
};
|
||||
const wins = this.readWins();
|
||||
return medalOrder.map((medal) => {
|
||||
const earned = wins.has(medal);
|
||||
const mask = medalMaskUrl;
|
||||
return html`<div
|
||||
class="w-5 h-5 ${earned ? "opacity-100" : "opacity-25"}"
|
||||
style="background-color:${colors[
|
||||
medal
|
||||
]}; mask: ${mask}; -webkit-mask: ${mask};"
|
||||
title=${translateText(`difficulty.${medal.toLowerCase()}`)}
|
||||
></div>`;
|
||||
});
|
||||
return MEDAL_ORDER.map((medal) =>
|
||||
medalIcon(medal, "w-5 h-5", wins.has(medal)),
|
||||
);
|
||||
}
|
||||
|
||||
private readWins(): Set<Difficulty> {
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import { html, TemplateResult } from "lit";
|
||||
import medalIconRaw from "../../../../resources/images/MedalIconWhite.svg?raw";
|
||||
import { Difficulty } from "../../../core/game/Game";
|
||||
import { translateText } from "../../Utils";
|
||||
|
||||
// CSS mask that renders the medal glyph; tint it via `background-color`.
|
||||
export const MEDAL_MASK = `url('data:image/svg+xml;utf8,${encodeURIComponent(medalIconRaw)}') no-repeat center / contain`;
|
||||
|
||||
// Difficulty medals, easiest to hardest — the canonical display order.
|
||||
export const MEDAL_ORDER: readonly Difficulty[] = [
|
||||
Difficulty.Easy,
|
||||
Difficulty.Medium,
|
||||
Difficulty.Hard,
|
||||
Difficulty.Impossible,
|
||||
];
|
||||
|
||||
export const MEDAL_COLORS: Record<Difficulty, string> = {
|
||||
[Difficulty.Easy]: "var(--medal-easy)",
|
||||
[Difficulty.Medium]: "var(--medal-medium)",
|
||||
[Difficulty.Hard]: "var(--medal-hard)",
|
||||
[Difficulty.Impossible]: "var(--medal-impossible)",
|
||||
};
|
||||
|
||||
/**
|
||||
* A single colored medal glyph. Pass `earned=false` to dim it so it reads as
|
||||
* "not yet won" (used on map cards); the overview keeps them full-color.
|
||||
*/
|
||||
export function medalIcon(
|
||||
difficulty: Difficulty,
|
||||
sizeClass = "w-5 h-5",
|
||||
earned = true,
|
||||
): TemplateResult {
|
||||
return html`<div
|
||||
class="${sizeClass} ${earned ? "opacity-100" : "opacity-25"}"
|
||||
style="background-color:${MEDAL_COLORS[
|
||||
difficulty
|
||||
]}; mask:${MEDAL_MASK}; -webkit-mask:${MEDAL_MASK};"
|
||||
title=${translateText(`difficulty.${difficulty.toLowerCase()}`)}
|
||||
></div>`;
|
||||
}
|
||||
Reference in New Issue
Block a user