mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-28 04:34:15 +00:00
629ce68604
## Description: With the alert frame, we're notified and can view the event using a “Focus” button that moves the map to the traitor, or dismiss it with a “Dismiss” button. The alert auto-dismisses after a few seconds. **Because this feature provides an advantage, the trade-off is having to wait a full 10 seconds or manually clicking “Dismiss” to close it.** - Show a red alert frame animation when the player is betrayed. - ~~The alert frame can be dismissed manually.~~ - The alert frame is automatically dismissed after ~~10~~ 3 seconds. - If the user doesn’t want to see it at all, they can disable it in the settings.     ## 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 - [x] I understand that submitting code with bugs that could have been caught through manual testing blocks releases and new features for all contributors ## Please put your Discord username so you can be contacted if a bug or regression is found: This is my first PR let me know if anything needs improvement! devalnor
133 lines
2.9 KiB
TypeScript
133 lines
2.9 KiB
TypeScript
import { LitElement, css, html } from "lit";
|
|
import { customElement, state } from "lit/decorators.js";
|
|
import {
|
|
BrokeAllianceUpdate,
|
|
GameUpdateType,
|
|
} from "../../../core/game/GameUpdates";
|
|
import { GameView } from "../../../core/game/GameView";
|
|
import { UserSettings } from "../../../core/game/UserSettings";
|
|
import { Layer } from "./Layer";
|
|
|
|
// Parameters for the alert animation
|
|
const ALERT_SPEED = 1.6;
|
|
const ALERT_COUNT = 2;
|
|
|
|
@customElement("alert-frame")
|
|
export class AlertFrame extends LitElement implements Layer {
|
|
public game: GameView;
|
|
private userSettings: UserSettings = new UserSettings();
|
|
|
|
@state()
|
|
private isActive = false;
|
|
|
|
private animationTimeout: number | null = null;
|
|
|
|
static styles = css`
|
|
.alert-border {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
pointer-events: none;
|
|
border: 17px solid #ee0000;
|
|
box-sizing: border-box;
|
|
z-index: 40;
|
|
opacity: 0;
|
|
}
|
|
|
|
.alert-border.animate {
|
|
animation: alertBlink ${ALERT_SPEED}s ease-in-out ${ALERT_COUNT};
|
|
}
|
|
|
|
@keyframes alertBlink {
|
|
0% {
|
|
opacity: 0;
|
|
}
|
|
50% {
|
|
opacity: 1;
|
|
}
|
|
100% {
|
|
opacity: 0;
|
|
}
|
|
}
|
|
`;
|
|
|
|
constructor() {
|
|
super();
|
|
if (!document.querySelector("style[data-alert-frame]")) {
|
|
const styleEl = document.createElement("style");
|
|
styleEl.setAttribute("data-alert-frame", "");
|
|
styleEl.textContent = AlertFrame.styles.cssText;
|
|
document.head.appendChild(styleEl);
|
|
}
|
|
}
|
|
|
|
createRenderRoot() {
|
|
return this;
|
|
}
|
|
|
|
init() {
|
|
// Listen for BrokeAllianceUpdate events directly from game updates
|
|
}
|
|
|
|
tick() {
|
|
if (!this.game) {
|
|
return; // Game not initialized yet
|
|
}
|
|
|
|
// Check for BrokeAllianceUpdate events
|
|
this.game
|
|
.updatesSinceLastTick()
|
|
?.[GameUpdateType.BrokeAlliance]?.forEach((update) => {
|
|
this.onBrokeAllianceUpdate(update as BrokeAllianceUpdate);
|
|
});
|
|
}
|
|
|
|
// The alert frame is not affected by the camera transform
|
|
shouldTransform(): boolean {
|
|
return false;
|
|
}
|
|
|
|
private onBrokeAllianceUpdate(update: BrokeAllianceUpdate) {
|
|
const myPlayer = this.game.myPlayer();
|
|
if (!myPlayer) return;
|
|
|
|
const betrayed = this.game.playerBySmallID(update.betrayedID);
|
|
|
|
// Only trigger alert if the current player is the betrayed one
|
|
if (betrayed === myPlayer) {
|
|
this.activateAlert();
|
|
}
|
|
}
|
|
|
|
private activateAlert() {
|
|
if (this.userSettings.alertFrame()) {
|
|
this.isActive = true;
|
|
this.requestUpdate();
|
|
}
|
|
}
|
|
|
|
public dismissAlert() {
|
|
this.isActive = false;
|
|
if (this.animationTimeout) {
|
|
clearTimeout(this.animationTimeout);
|
|
this.animationTimeout = null;
|
|
}
|
|
this.requestUpdate();
|
|
}
|
|
|
|
render() {
|
|
if (!this.isActive) {
|
|
return html``;
|
|
}
|
|
|
|
return html`
|
|
<div
|
|
class="alert-border animate"
|
|
@animationend=${() => this.dismissAlert()}
|
|
></div>
|
|
`;
|
|
}
|
|
}
|