[small-fix 20 lines] Add FFA collusion warning (#4107)

Resolves #3900

## Description:
During the spawn phase in FFA games, display a collusion warning to
clearly communicate to new users that pre-game agreement is not allowed.
<img width="1362" height="662" alt="2026-06-01_20-31"
src="https://github.com/user-attachments/assets/bd083e91-280a-41e1-a11a-d69d5f16bc8a"
/>

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

goose126

---------

Co-authored-by: evanpelle <evanpelle@gmail.com>
This commit is contained in:
a-happy-goose
2026-06-11 16:15:34 -03:00
committed by GitHub
parent 7405339ea7
commit 625d54c128
2 changed files with 40 additions and 1 deletions
+2
View File
@@ -1254,6 +1254,8 @@
"heads_up_message": {
"choose_spawn": "Choose a starting location",
"random_spawn": "Random spawn is enabled. Selecting starting location for you...",
"ffa_collusion": "Reminder: teaming up before the game is not allowed in FFA",
"dont_show_again": "Don't show again",
"singleplayer_game_paused": "Game paused",
"multiplayer_game_paused": "Game paused by Lobby Creator",
"pvp_immunity_active": "PVP immunity active for {seconds}s",
+38 -1
View File
@@ -1,11 +1,13 @@
import { LitElement, html } from "lit";
import { customElement, state } from "lit/decorators.js";
import { GameType } from "../../../core/game/Game";
import { GameMode, GameType } from "../../../core/game/Game";
import { GameUpdateType } from "../../../core/game/GameUpdates";
import { GameView } from "../../../core/game/GameView";
import { Controller } from "../../Controller";
import { translateText } from "../../Utils";
const COLLUSION_WARNING_CLOSED_KEY = "hasClosedCollusionWarning";
@customElement("heads-up-message")
export class HeadsUpMessage extends LitElement implements Controller {
public game: GameView;
@@ -13,6 +15,10 @@ export class HeadsUpMessage extends LitElement implements Controller {
@state()
private isVisible = false;
@state()
private hasClosedCollusionWarning =
localStorage.getItem(COLLUSION_WARNING_CLOSED_KEY) !== null;
@state()
private isPaused = false;
@@ -139,6 +145,12 @@ export class HeadsUpMessage extends LitElement implements Controller {
: translateText("heads_up_message.choose_spawn");
}
private onCloseCollusionWarning = (): void => {
localStorage.setItem(COLLUSION_WARNING_CLOSED_KEY, "true");
this.hasClosedCollusionWarning = true;
this.requestUpdate();
};
render() {
return html`
<div style="pointer-events: none;">
@@ -182,6 +194,31 @@ export class HeadsUpMessage extends LitElement implements Controller {
</div>
`
: null}
${this.game.inSpawnPhase() &&
this.game.config().gameConfig().gameMode === GameMode.FFA &&
this.game.config().gameConfig().gameType === GameType.Public &&
!this.hasClosedCollusionWarning
? html`
<div
class="fixed top-[25%] left-1/2 -translate-x-1/2 z-[799]
inline-flex flex-col items-center justify-center min-h-8 lg:min-h-10
w-fit max-w-[90vw]
bg-amber-500/70 rounded-md lg:rounded-lg
backdrop-blur-xs text-white text-md lg:text-xl px-3 lg:px-4 py-3
text-center break-words"
style="word-wrap: break-word; hyphens: auto; pointer-events: auto;"
@contextmenu=${(e: MouseEvent) => e.preventDefault()}
>
<div>${translateText("heads_up_message.ffa_collusion")}</div>
<button
class="mt-2 px-3 py-1 rounded bg-black/20 hover:bg-black/30 text-sm"
@click=${this.onCloseCollusionWarning}
>
${translateText("heads_up_message.dont_show_again")}
</button>
</div>
`
: null}
</div>
`;
}