Feat: Singleplayer Achievements (#2734)

Contributes towards the ongoing task of adding achievements: #2706

## Description:
Introduces a concept design and API implementation for singleplayer win
achievements. New row of ~5~ 4 medals is added to the map select screen
in the Singleplayer modal, one for each difficulty:
<img width="3132" height="779" alt="image"
src="https://github.com/user-attachments/assets/da8f0314-ccad-4f45-a03f-1beb46981301"
/>

In order to achieve a medal in a particular map, you must win the
singleplayer game (multiplayer and private match games don't count) in
the selected difficulty **without tampering with the options or
settings**. If any setting is changed from the default, regardless of
the difficulty, you will ~receive a fifth "Custom" medal~ not receive
the medal for that difficulty. Team games **do not** count towards the
medal achievement.

Completion of a medal will fill in the full correct color, as defined in
our `variables.css`:
<img width="694" height="778" alt="image"
src="https://github.com/user-attachments/assets/1b2d8370-aa86-4329-9402-adf43f3ef799"
/>

Completion medals can be toggled on or off (hidden by default) with the
toggle button at the top of the section:


https://github.com/user-attachments/assets/d08a58e0-b534-430e-9e8f-559134ad8852


[API implementation PR](https://github.com/openfrontio/infra/pull/234)

## 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:

bijx

---------

Co-authored-by: iamlewis <lewismmmm@gmail.com>
Co-authored-by: Evan <evanpelle@gmail.com>
This commit is contained in:
bijx
2026-01-05 16:27:36 -08:00
committed by GitHub
co-authored by iamlewis Evan
parent ecc174d248
commit b9f4a8d77b
7 changed files with 243 additions and 4 deletions
+13
View File
@@ -42,6 +42,11 @@ export const DiscordUserSchema = z.object({
});
export type DiscordUser = z.infer<typeof DiscordUserSchema>;
const SingleplayerMapAchievementSchema = z.object({
mapName: z.enum(GameMapType),
difficulty: z.enum(Difficulty),
});
export const UserMeResponseSchema = z.object({
user: z.object({
discord: DiscordUserSchema.optional(),
@@ -51,6 +56,14 @@ export const UserMeResponseSchema = z.object({
publicId: z.string(),
roles: z.string().array().optional(),
flares: z.string().array().optional(),
achievements: z
.array(
z.object({
type: z.literal("singleplayer-map"), // TODO: change the shape to be more flexible when we have more achievements
data: z.array(SingleplayerMapAchievementSchema),
}),
)
.optional(),
}),
});
export type UserMeResponse = z.infer<typeof UserMeResponseSchema>;