The problem
Battlefield 6 launched with Portal, a toolkit for building custom modes in code. I wanted the Team Deathmatch that players of older shooters remember: a short freeze time, first team to 75 kills wins, a clear scoreboard, and respawns that don't drop you in front of the enemy.
What I built
A Portal experience written in TypeScript against the official SDK and bundled with esbuild. Matches open with a 15-second freeze-time countdown, then run for 10 minutes or until a team reaches 75 kills. A custom HUD shows both teams' scores, the target and the clock; a custom scoreboard tracks kills, deaths, assists, K/D and headshot rate per player. The announcer reacts at 20, 40 and 65 kills, whenever the lead changes, and at two minutes, one minute and 30 seconds left. Spawn points are props placed in the SDK's Godot scenes for two maps, read at match start by their ids.
Technical challenges
- Fair spawns. For each respawn I measure, for every spawn point, the distance to the nearest living enemy, keep the points within 80% of the safest one, and pick one at random. Spawns stay safe without becoming predictable.
- An early SDK. Asking for a missing object still returns one, so spawn points are detected by checking their position by hand; objects couldn't be disabled, so used markers are moved out of the map. Each workaround is commented in the code.
- Scoreboard sorting. One overload of the sort call is zero-based while documented as one-based. A contributor's pull request fixed the sorting and added a dynamic header, and I merged it.
Outcome
I built the mode in the two weeks after Battlefield 6's launch, and its source is public on GitHub. It is no longer maintained.