From de33c91dbe94d8e9005ec98fa1226330617705f4 Mon Sep 17 00:00:00 2001 From: itsnobii <57056220+itsnobii@users.noreply.github.com> Date: Tue, 14 Oct 2025 18:28:11 -0400 Subject: [PATCH 1/5] implement timeout counters for each team --- src/connector/databaseConnector.ts | 6 +- src/connector/websocketOutgoing.ts | 4 + src/model/Match.ts | 114 ++++++++++++++++++++++++----- src/model/ToolsData.ts | 10 +++ 4 files changed, 113 insertions(+), 21 deletions(-) diff --git a/src/connector/databaseConnector.ts b/src/connector/databaseConnector.ts index 9143e26..2d5a18a 100644 --- a/src/connector/databaseConnector.ts +++ b/src/connector/databaseConnector.ts @@ -62,7 +62,7 @@ export class DatabaseConnector { public static async registerMatch(match: any) { // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { replayLog, eventNumber, timeoutEndTimeout, timeoutRemainingLoop, ...toSend } = match; + const { replayLog, eventNumber, timeoutEndTimeout, timeoutRemainingLoop, leftTimeoutCancellationTimer, rightTimeoutCancellationTimer, ...toSend } = match; const res = await this.apiRequest(`system/match/${match.matchId}/register`, "post", { match: toSend, }); @@ -77,7 +77,7 @@ export class DatabaseConnector { public static async updateMatch(match: any): Promise { // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { replayLog, eventNumber, timeoutEndTimeout, timeoutRemainingLoop, ...toSend } = match; + const { replayLog, eventNumber, timeoutEndTimeout, timeoutRemainingLoop, leftTimeoutCancellationTimer, rightTimeoutCancellationTimer, ...toSend } = match; const res = await this.apiRequest(`system/match/${match.matchId}/update`, "put", { match: toSend, }); @@ -92,7 +92,7 @@ export class DatabaseConnector { public static async completeMatch(match: any): Promise { // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { replayLog, eventNumber, timeoutEndTimeout, timeoutRemainingLoop, ...toSend } = match; + const { replayLog, eventNumber, timeoutEndTimeout, timeoutRemainingLoop, leftTimeoutCancellationTimer, rightTimeoutCancellationTimer, ...toSend } = match; const res = await this.apiRequest(`system/match/${match.matchId}/complete`, "put", { match: toSend, }); diff --git a/src/connector/websocketOutgoing.ts b/src/connector/websocketOutgoing.ts index 5898403..7d047e6 100644 --- a/src/connector/websocketOutgoing.ts +++ b/src/connector/websocketOutgoing.ts @@ -95,6 +95,10 @@ export class WebsocketOutgoing { // eslint-disable-next-line @typescript-eslint/no-unused-vars timeoutRemainingLoop, // eslint-disable-next-line @typescript-eslint/no-unused-vars + leftTimeoutCancellationTimer, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + rightTimeoutCancellationTimer, + // eslint-disable-next-line @typescript-eslint/no-unused-vars playercamUrl, ...formattedData } = data; diff --git a/src/model/Match.ts b/src/model/Match.ts index cfc267c..c1d455f 100644 --- a/src/model/Match.ts +++ b/src/model/Match.ts @@ -49,6 +49,10 @@ export class Match { }; private timeoutEndTimeout: any = undefined; private timeoutRemainingLoop: any = undefined; + + private leftTimeoutCancellationTimer: any = undefined; + private rightTimeoutCancellationTimer: any = undefined; + private hasEnteredOvertime: boolean = false; private tools: ToolsData; @@ -201,6 +205,8 @@ export class Match { this.processRoundReasons(); } + this.checkAndGrantOvertimeTimeout(); + if (process.env.USE_BACKEND === "true") { this.updateNameOverridesAndPlayercams().then(() => {}); } @@ -238,6 +244,13 @@ export class Match { case "game_end": this.isRunning = false; + + // Clean up all timeout-related timers + clearTimeout(this.leftTimeoutCancellationTimer); + clearTimeout(this.rightTimeoutCancellationTimer); + this.leftTimeoutCancellationTimer = undefined; + this.rightTimeoutCancellationTimer = undefined; + this.eventNumber++; MatchController.getInstance().removeMatch(this.groupCode); @@ -293,31 +306,21 @@ export class Match { clearTimeout(this.timeoutEndTimeout); clearInterval(this.timeoutRemainingLoop); this.timeoutEndTimeout = null; + + // Clean up cancellation timers + clearTimeout(this.leftTimeoutCancellationTimer); + clearTimeout(this.rightTimeoutCancellationTimer); + this.leftTimeoutCancellationTimer = undefined; + this.rightTimeoutCancellationTimer = undefined; } break; case DataTypes.LEFT_TIMEOUT: - this.timeoutState.leftTeam = !this.timeoutState.leftTeam; - if (this.timeoutState.leftTeam) { - this.timeoutState.rightTeam = false; - this.timeoutState.techPause = false; - this.timeoutState.timeRemaining = this.tools.timeoutDuration; - this.startTimeoutEndTimeout(); - } else { - clearTimeout(this.timeoutEndTimeout); - } + this.handleTeamTimeout("left"); break; case DataTypes.RIGHT_TIMEOUT: - this.timeoutState.rightTeam = !this.timeoutState.rightTeam; - if (this.timeoutState.rightTeam) { - this.timeoutState.leftTeam = false; - this.timeoutState.techPause = false; - this.timeoutState.timeRemaining = this.tools.timeoutDuration; - this.startTimeoutEndTimeout(); - } else { - clearTimeout(this.timeoutEndTimeout); - } + this.handleTeamTimeout("right"); break; case DataTypes.SWITCH_KDA_CREDITS: @@ -439,6 +442,81 @@ export class Match { this.spikeDetonationTime = timestamp + 45 * 1000; // Add 45 seconds to the current time } + private handleTeamTimeout(team: "left" | "right") { + const isLeftTeam = team === "left"; + const currentState = isLeftTeam ? this.timeoutState.leftTeam : this.timeoutState.rightTeam; + const cancellationTimer = isLeftTeam ? this.leftTimeoutCancellationTimer : this.rightTimeoutCancellationTimer; + + if (cancellationTimer) { + clearTimeout(cancellationTimer); + if (isLeftTeam) { + this.leftTimeoutCancellationTimer = undefined; + } else { + this.rightTimeoutCancellationTimer = undefined; + } + + // Stop the current timeout + this.timeoutState.leftTeam = false; + this.timeoutState.rightTeam = false; + clearTimeout(this.timeoutEndTimeout); + clearInterval(this.timeoutRemainingLoop); + this.timeoutEndTimeout = undefined; + this.timeoutRemainingLoop = undefined; + + return; + } + + if (currentState) { + this.timeoutState.leftTeam = false; + this.timeoutState.rightTeam = false; + clearTimeout(this.timeoutEndTimeout); + clearInterval(this.timeoutRemainingLoop); + this.timeoutEndTimeout = undefined; + this.timeoutRemainingLoop = undefined; + } else { + const timeoutsRemaining = isLeftTeam ? this.tools.timeoutCounter.left : this.tools.timeoutCounter.right; + + if (timeoutsRemaining <= 0) { + return; + } + + this.timeoutState.leftTeam = isLeftTeam; + this.timeoutState.rightTeam = !isLeftTeam; + this.timeoutState.techPause = false; + this.timeoutState.timeRemaining = this.tools.timeoutDuration; + this.startTimeoutEndTimeout(); + + const gracePeriodTimer = setTimeout(() => { + if (isLeftTeam) { + this.tools.timeoutCounter.left = Math.max(0, this.tools.timeoutCounter.left - 1); + this.leftTimeoutCancellationTimer = undefined; + } else { + this.tools.timeoutCounter.right = Math.max(0, this.tools.timeoutCounter.right - 1); + this.rightTimeoutCancellationTimer = undefined; + } + this.eventNumber++; + }, this.tools.timeoutCancellationGracePeriod * 1000); + + if (isLeftTeam) { + this.leftTimeoutCancellationTimer = gracePeriodTimer; + } else { + this.rightTimeoutCancellationTimer = gracePeriodTimer; + } + } + } + + private checkAndGrantOvertimeTimeout() { + if (this.roundNumber >= this.firstOtRound && !this.hasEnteredOvertime) { + this.hasEnteredOvertime = true; + + this.tools.timeoutCounter.left = Math.min(2, this.tools.timeoutCounter.left + 1); + this.tools.timeoutCounter.right = Math.min(2, this.tools.timeoutCounter.right + 1); + + this.eventNumber++; + Log.info(`Overtime reached! Each team granted an additional timeout.`); + } + } + private async updateNameOverridesAndPlayercams() { if ( !this.tools.playercamsInfo.identifier || diff --git a/src/model/ToolsData.ts b/src/model/ToolsData.ts index 983125a..ae2c6fd 100644 --- a/src/model/ToolsData.ts +++ b/src/model/ToolsData.ts @@ -16,6 +16,11 @@ export class ToolsData { enabled: false, }; public timeoutDuration: number = 60; + public timeoutCounter: ITimeoutInfo = { + left: 2, + right: 2, + }; + public timeoutCancellationGracePeriod: number = 10; public sponsorInfo: ISponsorInfo = { enabled: false, duration: 5, @@ -68,6 +73,11 @@ export type ITournamentInfo = { enabled: boolean; }; +export type ITimeoutInfo = { + left: number; + right: number; +}; + export type ISponsorInfo = { enabled: boolean; duration: number; From 3c9fe907962cdfe005acd8f084abdca314533c4f Mon Sep 17 00:00:00 2001 From: itsnobii <57056220+itsnobii@users.noreply.github.com> Date: Thu, 16 Oct 2025 22:34:32 -0400 Subject: [PATCH 2/5] Change timeout to only deduct at the end of the timer, update to check `timeoutState.timeRemaining` rather than creating new timeouts --- src/connector/websocketOutgoing.ts | 10 +--- src/model/Match.ts | 77 +++++++++++------------------- 2 files changed, 29 insertions(+), 58 deletions(-) diff --git a/src/connector/websocketOutgoing.ts b/src/connector/websocketOutgoing.ts index 7d047e6..a209211 100644 --- a/src/connector/websocketOutgoing.ts +++ b/src/connector/websocketOutgoing.ts @@ -91,17 +91,9 @@ export class WebsocketOutgoing { // eslint-disable-next-line @typescript-eslint/no-unused-vars eventNumber, // eslint-disable-next-line @typescript-eslint/no-unused-vars - timeoutEndTimeout, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - timeoutRemainingLoop, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - leftTimeoutCancellationTimer, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - rightTimeoutCancellationTimer, - // eslint-disable-next-line @typescript-eslint/no-unused-vars playercamUrl, ...formattedData - } = data; + } = data; const deepMod: any = structuredClone(formattedData); if ( diff --git a/src/model/Match.ts b/src/model/Match.ts index c1d455f..bdcbf3b 100644 --- a/src/model/Match.ts +++ b/src/model/Match.ts @@ -49,9 +49,8 @@ export class Match { }; private timeoutEndTimeout: any = undefined; private timeoutRemainingLoop: any = undefined; + private timeoutGracePeriodPassed: boolean = false; - private leftTimeoutCancellationTimer: any = undefined; - private rightTimeoutCancellationTimer: any = undefined; private hasEnteredOvertime: boolean = false; private tools: ToolsData; @@ -245,11 +244,11 @@ export class Match { case "game_end": this.isRunning = false; - // Clean up all timeout-related timers - clearTimeout(this.leftTimeoutCancellationTimer); - clearTimeout(this.rightTimeoutCancellationTimer); - this.leftTimeoutCancellationTimer = undefined; - this.rightTimeoutCancellationTimer = undefined; + // Clean up timeout-related timers + clearTimeout(this.timeoutEndTimeout); + clearInterval(this.timeoutRemainingLoop); + this.timeoutEndTimeout = undefined; + this.timeoutRemainingLoop = undefined; this.eventNumber++; MatchController.getInstance().removeMatch(this.groupCode); @@ -306,12 +305,6 @@ export class Match { clearTimeout(this.timeoutEndTimeout); clearInterval(this.timeoutRemainingLoop); this.timeoutEndTimeout = null; - - // Clean up cancellation timers - clearTimeout(this.leftTimeoutCancellationTimer); - clearTimeout(this.rightTimeoutCancellationTimer); - this.leftTimeoutCancellationTimer = undefined; - this.rightTimeoutCancellationTimer = undefined; } break; @@ -337,8 +330,18 @@ export class Match { clearInterval(this.timeoutRemainingLoop); this.timeoutRemainingLoop = null; + + this.timeoutGracePeriodPassed = false; this.timeoutEndTimeout = setTimeout(() => { + if (this.timeoutGracePeriodPassed) { + if (this.timeoutState.leftTeam) { + this.tools.timeoutCounter.left = Math.max(0, this.tools.timeoutCounter.left - 1); + } else if (this.timeoutState.rightTeam) { + this.tools.timeoutCounter.right = Math.max(0, this.tools.timeoutCounter.right - 1); + } + } + this.timeoutState.leftTeam = false; this.timeoutState.rightTeam = false; clearInterval(this.timeoutRemainingLoop); @@ -348,6 +351,13 @@ export class Match { this.timeoutRemainingLoop = setInterval(() => { if (this.timeoutState.timeRemaining > 0) { this.timeoutState.timeRemaining--; + + // track if grace period has passed + const gracePeriodRemaining = this.tools.timeoutDuration - this.tools.timeoutCancellationGracePeriod; + if (!this.timeoutGracePeriodPassed && this.timeoutState.timeRemaining <= gracePeriodRemaining) { + this.timeoutGracePeriodPassed = true; + } + this.eventNumber++; } else { clearInterval(this.timeoutRemainingLoop); @@ -445,28 +455,14 @@ export class Match { private handleTeamTimeout(team: "left" | "right") { const isLeftTeam = team === "left"; const currentState = isLeftTeam ? this.timeoutState.leftTeam : this.timeoutState.rightTeam; - const cancellationTimer = isLeftTeam ? this.leftTimeoutCancellationTimer : this.rightTimeoutCancellationTimer; - if (cancellationTimer) { - clearTimeout(cancellationTimer); - if (isLeftTeam) { - this.leftTimeoutCancellationTimer = undefined; - } else { - this.rightTimeoutCancellationTimer = undefined; - } + if (currentState) { + const gracePeriodRemaining = this.tools.timeoutDuration - this.tools.timeoutCancellationGracePeriod; + const stillInGracePeriod = this.timeoutState.timeRemaining > gracePeriodRemaining; - // Stop the current timeout - this.timeoutState.leftTeam = false; - this.timeoutState.rightTeam = false; - clearTimeout(this.timeoutEndTimeout); - clearInterval(this.timeoutRemainingLoop); - this.timeoutEndTimeout = undefined; - this.timeoutRemainingLoop = undefined; + if (stillInGracePeriod && !this.timeoutGracePeriodPassed) { + } - return; - } - - if (currentState) { this.timeoutState.leftTeam = false; this.timeoutState.rightTeam = false; clearTimeout(this.timeoutEndTimeout); @@ -485,23 +481,6 @@ export class Match { this.timeoutState.techPause = false; this.timeoutState.timeRemaining = this.tools.timeoutDuration; this.startTimeoutEndTimeout(); - - const gracePeriodTimer = setTimeout(() => { - if (isLeftTeam) { - this.tools.timeoutCounter.left = Math.max(0, this.tools.timeoutCounter.left - 1); - this.leftTimeoutCancellationTimer = undefined; - } else { - this.tools.timeoutCounter.right = Math.max(0, this.tools.timeoutCounter.right - 1); - this.rightTimeoutCancellationTimer = undefined; - } - this.eventNumber++; - }, this.tools.timeoutCancellationGracePeriod * 1000); - - if (isLeftTeam) { - this.leftTimeoutCancellationTimer = gracePeriodTimer; - } else { - this.rightTimeoutCancellationTimer = gracePeriodTimer; - } } } From 8613c97b90a1908e5c15bd36e0c6d22cdaf2c00a Mon Sep 17 00:00:00 2001 From: itsnobii <57056220+itsnobii@users.noreply.github.com> Date: Fri, 17 Oct 2025 17:03:41 -0400 Subject: [PATCH 3/5] remove redundant new timeout creation from connector --- src/connector/databaseConnector.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/connector/databaseConnector.ts b/src/connector/databaseConnector.ts index 2d5a18a..9143e26 100644 --- a/src/connector/databaseConnector.ts +++ b/src/connector/databaseConnector.ts @@ -62,7 +62,7 @@ export class DatabaseConnector { public static async registerMatch(match: any) { // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { replayLog, eventNumber, timeoutEndTimeout, timeoutRemainingLoop, leftTimeoutCancellationTimer, rightTimeoutCancellationTimer, ...toSend } = match; + const { replayLog, eventNumber, timeoutEndTimeout, timeoutRemainingLoop, ...toSend } = match; const res = await this.apiRequest(`system/match/${match.matchId}/register`, "post", { match: toSend, }); @@ -77,7 +77,7 @@ export class DatabaseConnector { public static async updateMatch(match: any): Promise { // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { replayLog, eventNumber, timeoutEndTimeout, timeoutRemainingLoop, leftTimeoutCancellationTimer, rightTimeoutCancellationTimer, ...toSend } = match; + const { replayLog, eventNumber, timeoutEndTimeout, timeoutRemainingLoop, ...toSend } = match; const res = await this.apiRequest(`system/match/${match.matchId}/update`, "put", { match: toSend, }); @@ -92,7 +92,7 @@ export class DatabaseConnector { public static async completeMatch(match: any): Promise { // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { replayLog, eventNumber, timeoutEndTimeout, timeoutRemainingLoop, leftTimeoutCancellationTimer, rightTimeoutCancellationTimer, ...toSend } = match; + const { replayLog, eventNumber, timeoutEndTimeout, timeoutRemainingLoop, ...toSend } = match; const res = await this.apiRequest(`system/match/${match.matchId}/complete`, "put", { match: toSend, }); From f7aa1ad2db2bbfd7c13a87ca9b4e36e33fd6b026 Mon Sep 17 00:00:00 2001 From: itsnobii <57056220+itsnobii@users.noreply.github.com> Date: Mon, 3 Nov 2025 15:03:42 -0500 Subject: [PATCH 4/5] add timeouts back to websocketOutgoing and properly account for manually ending timeouts --- src/connector/websocketOutgoing.ts | 4 ++++ src/model/Match.ts | 19 ++++++++++++------- src/replay/ReplayConnectorService.ts | 5 +++++ 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/connector/websocketOutgoing.ts b/src/connector/websocketOutgoing.ts index a209211..34a01ec 100644 --- a/src/connector/websocketOutgoing.ts +++ b/src/connector/websocketOutgoing.ts @@ -92,6 +92,10 @@ export class WebsocketOutgoing { eventNumber, // eslint-disable-next-line @typescript-eslint/no-unused-vars playercamUrl, + timeoutEndTimeout, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + timeoutRemainingLoop, + // eslint-disable-next-line @typescript-eslint/no-unused-vars ...formattedData } = data; diff --git a/src/model/Match.ts b/src/model/Match.ts index bdcbf3b..dd35477 100644 --- a/src/model/Match.ts +++ b/src/model/Match.ts @@ -334,12 +334,10 @@ export class Match { this.timeoutGracePeriodPassed = false; this.timeoutEndTimeout = setTimeout(() => { - if (this.timeoutGracePeriodPassed) { - if (this.timeoutState.leftTeam) { - this.tools.timeoutCounter.left = Math.max(0, this.tools.timeoutCounter.left - 1); - } else if (this.timeoutState.rightTeam) { - this.tools.timeoutCounter.right = Math.max(0, this.tools.timeoutCounter.right - 1); - } + if (this.timeoutState.leftTeam) { + this.tools.timeoutCounter.left = Math.max(0, this.tools.timeoutCounter.left - 1); + } else if (this.timeoutState.rightTeam) { + this.tools.timeoutCounter.right = Math.max(0, this.tools.timeoutCounter.right - 1); } this.timeoutState.leftTeam = false; @@ -460,9 +458,16 @@ export class Match { const gracePeriodRemaining = this.tools.timeoutDuration - this.tools.timeoutCancellationGracePeriod; const stillInGracePeriod = this.timeoutState.timeRemaining > gracePeriodRemaining; - if (stillInGracePeriod && !this.timeoutGracePeriodPassed) { + // If grace period has passed, deduct a timeout + if (!stillInGracePeriod) { + if (isLeftTeam) { + this.tools.timeoutCounter.left = Math.max(0, this.tools.timeoutCounter.left - 1); + } else { + this.tools.timeoutCounter.right = Math.max(0, this.tools.timeoutCounter.right - 1); + } } + // Cancel the timeout this.timeoutState.leftTeam = false; this.timeoutState.rightTeam = false; clearTimeout(this.timeoutEndTimeout); diff --git a/src/replay/ReplayConnectorService.ts b/src/replay/ReplayConnectorService.ts index a8d00c6..5180ebc 100644 --- a/src/replay/ReplayConnectorService.ts +++ b/src/replay/ReplayConnectorService.ts @@ -134,6 +134,11 @@ export class ReplayConnectorService { nameOverrides: { overrides: "[]", }, + timeoutCounter: { + left: 2, + right: 2, + }, + timeoutCancellationGracePeriod: 10, }, }; this.ws.emit("obs_logon", JSON.stringify(authData)); From c4271f5d20b67c1348603d8fea325550c9cd2427 Mon Sep 17 00:00:00 2001 From: itsnobii <57056220+itsnobii@users.noreply.github.com> Date: Mon, 16 Mar 2026 23:47:45 -0400 Subject: [PATCH 5/5] Add live toast data --- src/connector/websocketOutgoing.ts | 2 ++ src/model/Match.ts | 28 ++++++++++++++++++++++++++++ src/model/ToolsData.ts | 15 +++++++++++++++ src/model/eventData.ts | 1 + 4 files changed, 46 insertions(+) diff --git a/src/connector/websocketOutgoing.ts b/src/connector/websocketOutgoing.ts index 688408f..979c28f 100644 --- a/src/connector/websocketOutgoing.ts +++ b/src/connector/websocketOutgoing.ts @@ -98,6 +98,8 @@ export class WebsocketOutgoing { timeoutEndTimeout, // eslint-disable-next-line @typescript-eslint/no-unused-vars timeoutRemainingLoop, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + toastEndTimeout, ...formattedData } = data; diff --git a/src/model/Match.ts b/src/model/Match.ts index c31e633..12e6daa 100644 --- a/src/model/Match.ts +++ b/src/model/Match.ts @@ -52,6 +52,8 @@ export class Match { private timeoutRemainingLoop: any = undefined; private timeoutGracePeriodPassed: boolean = false; + private toastEndTimeout: any = undefined; + private hasEnteredOvertime: boolean = false; private tools: ToolsData; @@ -346,6 +348,10 @@ export class Match { case DataTypes.SWITCH_KDA_CREDITS: this.showAliveKDA = !this.showAliveKDA; break; + + case DataTypes.TOAST: + this.handleToast(); + break; } this.eventNumber++; @@ -481,6 +487,28 @@ export class Match { this.spikeDetonationTime = timestamp + 45 * 1000; // Add 45 seconds to the current time } + private handleToast() { + if (this.tools.toastInfo.active) { + // Toast is active — deactivate it immediately + this.tools.toastInfo.active = false; + clearTimeout(this.toastEndTimeout); + this.toastEndTimeout = undefined; + } else { + // Activate the toast + this.tools.toastInfo.active = true; + + if (this.tools.toastInfo.duration !== null) { + // Auto-deactivate after the configured duration (ms) + this.toastEndTimeout = setTimeout(() => { + this.tools.toastInfo.active = false; + this.toastEndTimeout = undefined; + this.eventNumber++; + }, this.tools.toastInfo.duration); + } + // If duration is null, the toast stays until the hotkey is pressed again + } + } + private handleTeamTimeout(team: "left" | "right") { const isLeftTeam = team === "left"; const currentState = isLeftTeam ? this.timeoutState.leftTeam : this.timeoutState.rightTeam; diff --git a/src/model/ToolsData.ts b/src/model/ToolsData.ts index 4f8ed0e..bbec5c2 100644 --- a/src/model/ToolsData.ts +++ b/src/model/ToolsData.ts @@ -43,6 +43,13 @@ export class ToolsData { public nameOverrides: INameOverrides = { overrides: "[]", }; + public toastInfo: IToastInfo = { + duration: null, + message: "", + eventLogoEnabled: true, + selectedTeam: undefined, + active: false, + }; public constructor(init?: Partial) { Object.assign(this, init); @@ -112,6 +119,14 @@ export type IOverridesPlayercamsData = { enabledPlayers: string[]; }; +export type IToastInfo = { + duration: number | null; + message: string; + eventLogoEnabled: boolean; + selectedTeam ?: "left" | "right"; + active: boolean; +}; + type BaseMapPoolInfo = { type: "past" | "present" | "future" | "disabled"; }; diff --git a/src/model/eventData.ts b/src/model/eventData.ts index 6e9c9ce..b7a37d1 100644 --- a/src/model/eventData.ts +++ b/src/model/eventData.ts @@ -180,6 +180,7 @@ export enum DataTypes { LEFT_TIMEOUT = "left_timeout", RIGHT_TIMEOUT = "right_timeout", SWITCH_KDA_CREDITS = "switch_kda_credits", + TOAST = "toast", // Preview data types PREVIEW = "preview", }