More.tf Map Overview

A screenshot of a match log on more.tf, displaying the player performance tab

Nobody can deny that the TF2 community is not a passionate one, and the people who love to visualize match data from competitive seasons are no exception. More.tf is the culmination of nearly two decades of that passion in one website. It’s a stellar tool that allows comp players to visualize and analyze play styles, performance, and map skill of themselves, their teammates, and their opponents.

A screenshot of the more.tf profile page for the Team Fortress 2 player b4nny.
The more.tf profile page for one of the top competitive players, b4nny.

Regular readers will know that I am pretty deeply involved with the 4v4 PASS Time community. I play matches, I make a lot of art, and I hang out with the lovely people who align themselves with that game mode. 4v4PT is a competitive area of Team Fortress 2. Its popularity in the larger competitive scene is and has been rising for a while now.

The Problem

Up until a few months ago, more.tf’s representation of the relatively new 4v4PT game mode was lackluster. This was no fault of the two developers. The site overworked them as is. I reached out to Mori, the head of the project, to ask how I could help to fix that. He happily hopped on a Discord call with me and walked me through installing the dependencies. Then he showed me how to capture, upload, and calibrate custom map images.

I came to find out that the calculations for displaying the kill tracker icons on top of a particular map image were guesswork. He revealed to me that he would capture the map image and just guess the calibrations. I was stunned.

Immediately, I asked if I could try and take a look through the code to see if I could provide a better solution for this system. Mori was more than happy to give the green light. A project that handles the parsing and visualizing of millions of logs of game data with just two consistent volunteer developers needs any additional help possible. I started looking into the code straight away. I discovered an important stopgap: I have no idea how to read or write JavaScript.

That didn’t stop me. Even in an unintelligible programming language, numbers and variables are quite constant. I identified the bit of code responsible for calculating the player positions on the map. Now all I had to do was figure out what data was available to me from the game or screenshot. With relevant data, I could make the map faster and easier to set up on the dev side. Additionally, I could make it more accurate and consistent for users.

Data-Driven

Since killer and victim icons on the map are based on in-game coordinates, I would only need three pieces of data to replace the guesswork variables already put in place by Mori: Scale, x offset, and y offset. I dove into Valve’s documentation for the command that allows people to take level overview screenshots (cl_leveloverview <scale>). This command is, like the rest of the Source engine, very antiquated and incredibly specifically designed. More specifically, they designed it for a game that isn’t Team Fortress 2.

Scale

However, the first piece of necessary data was easy to obtain. More.tf already included scale as a variable. The command itself also gives it in a different form. The only required parameter for cl_leveloverview sets the scale of the overview image. cl_leveloverview 1 means that the entire height of your screen is 1024 Hammer units (in-game coordinate unit) and, for typical 16 to 9 screens, the entire width of your screen is 1820 hU. Any value besides 0 or 1 would multiply those units by itself.

Offsets

The other two pieces of data, the coordinate offsets, were already programmed into the original code as well. However, they only served to center the points on the map because the original code centered its 0, 0 in the top-left corner of the map and needed to be recentered in the actual center. I needed to provide one consistently retrievable set of offset numbers to more.tf that could adjust the coordinates if the center point or perceived center point of the map was not on the origin in-game. This happens a lot in Source engine game maps, because 0, 0, 0 causes issues with the visibility calculations on compile, so many custom mappers opt to offset their map from the origin to avoid the problems that might arise.

A level overview image for the Team Fortress 2 map cp_proworks with the player's position coordinates included
The x and y positions for the center of the map cp_proworks are 159, -873.

I sat in-game, wracking my brain for a solution, when I opened the console and noticed something strange. The console had sent nearly the same message nearly 1000 times. Upon closer inspection, the game handed me the information I needed on a silver platter. It gave me the x and y coordinates of the spot located in the top-left of my screen. It updated this value every time I moved in-game.

The Math

With this discovery, I jumped to finding what calculations would work for every scale and coordinate system. I came up with this:

The “+ 910 * currentScale” and “- 512 * currentScale” center the calibration coordinates from the top left of the screen. (At 1x scale, the top-left coordinates are -910, 512 for 0, 0. It’s funny how that’s exactly half the total coordinate screen width and height that I mentioned earlier, huh?). Then you add in the calibration coordinate and subtract it from the given coordinate position. This results in a coordinate set not constrained by scale. Maps with larger scales would end up with physically larger coordinate sets on screen. That’s why I divide by the scale again. This results in a consistent coordinate set from -512 to 512 on both axes.

The final step is getting it ready to display in browser units. Most modern websites are designed around using relative, responsive sizes. That way, the website conforms to the size and ratio of the user’s screen. The old more.tf map used something like 417×417, which was an absolute size. Instead, I multiply by that long decimal (don’t ask me why I didn’t divide; I don’t know either) to convert it to a range of -50 to +50. Then, I add 50 to get it from 0 to 100, and finally stick a percentage sign onto the end using the braces. I don’t remember the actual JS name for those. This is all so that each coordinate is converted into a percentage FROM left TO right and FROM top TO bottom relative to the parent element of the map.

The Aftermath

As it turns out, you can’t upend a website’s coordinate calculations and expect the existing map images and calibration references to work. It took me around a week of very lazy on-and-off work to get all of the existing maps, as well as some new ones, captured and updated for the new system.

Then, I had the rare pleasure of learning how to pull request and seeing my code go live on the site. 😀

Now I’m working on the side with the lovely more.tf team on more site improvements and bug fixes, although I must admit I know so little about the actual programming that around 95% of it is still going over my head. I’m using this project as a stressful but fun way to learn JavaScript by jumping into the deep end. Be sure to check out more.tf at least once, especially if you’ve played competitive TF2 before! If you haven’t and you still want to see it in action, just pick a random player from the summaries or leaderboards.

Leave a Reply

Your email address will not be published. Required fields are marked *