Files
OpenFrontIO/src/core/execution/WinCheckExecution.ts
T
Vivacious Box f161c94ff4 Max timer (#1289)
## Description:

Adds a max timer setting
The timer starts at max timer and goes down, becoming red if reaching <
1 min
The player with the biggest territory wins at the end of the timer


![image](https://github.com/user-attachments/assets/888099fc-95ae-4303-8c80-c850e58d36e2)

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

Vivacious Box

---------

Co-authored-by: Loymdayddaud <145969603+TheGiraffe3@users.noreply.github.com>
2025-10-17 17:09:10 -07:00

108 lines
2.9 KiB
TypeScript

import { GameEvent } from "../EventBus";
import {
ColoredTeams,
Execution,
Game,
GameMode,
Player,
Team,
} from "../game/Game";
export class WinEvent implements GameEvent {
constructor(public readonly winner: Player) {}
}
export class WinCheckExecution implements Execution {
private active = true;
private mg: Game | null = null;
constructor() {}
init(mg: Game, ticks: number) {
this.mg = mg;
}
tick(ticks: number) {
if (ticks % 10 !== 0) {
return;
}
if (this.mg === null) throw new Error("Not initialized");
if (this.mg.config().gameConfig().gameMode === GameMode.FFA) {
this.checkWinnerFFA();
} else {
this.checkWinnerTeam();
}
}
checkWinnerFFA(): void {
if (this.mg === null) throw new Error("Not initialized");
const sorted = this.mg
.players()
.sort((a, b) => b.numTilesOwned() - a.numTilesOwned());
if (sorted.length === 0) {
return;
}
const max = sorted[0];
const timeElapsed =
(this.mg.ticks() - this.mg.config().numSpawnPhaseTurns()) / 10;
const numTilesWithoutFallout =
this.mg.numLandTiles() - this.mg.numTilesWithFallout();
if (
(max.numTilesOwned() / numTilesWithoutFallout) * 100 >
this.mg.config().percentageTilesOwnedToWin() ||
(this.mg.config().gameConfig().maxTimerValue !== undefined &&
timeElapsed - this.mg.config().gameConfig().maxTimerValue! * 60 >= 0)
) {
this.mg.setWinner(max, this.mg.stats().stats());
console.log(`${max.name()} has won the game`);
this.active = false;
}
}
checkWinnerTeam(): void {
if (this.mg === null) throw new Error("Not initialized");
const teamToTiles = new Map<Team, number>();
for (const player of this.mg.players()) {
const team = player.team();
// Sanity check, team should not be null here
if (team === null) continue;
teamToTiles.set(
team,
(teamToTiles.get(team) ?? 0) + player.numTilesOwned(),
);
}
const sorted = Array.from(teamToTiles.entries()).sort(
(a, b) => b[1] - a[1],
);
if (sorted.length === 0) {
return;
}
const max = sorted[0];
const timeElapsed =
(this.mg.ticks() - this.mg.config().numSpawnPhaseTurns()) / 10;
const numTilesWithoutFallout =
this.mg.numLandTiles() - this.mg.numTilesWithFallout();
const percentage = (max[1] / numTilesWithoutFallout) * 100;
if (
percentage > this.mg.config().percentageTilesOwnedToWin() ||
(this.mg.config().gameConfig().maxTimerValue !== undefined &&
timeElapsed - this.mg.config().gameConfig().maxTimerValue! * 60 >= 0)
) {
if (max[0] === ColoredTeams.Bot) return;
this.mg.setWinner(max[0], this.mg.stats().stats());
console.log(`${max[0]} has won the game`);
this.active = false;
}
}
isActive(): boolean {
return this.active;
}
activeDuringSpawnPhase(): boolean {
return false;
}
}