The blog for the bleeding-edge news in the server of Research and Development.

Why TF2 painted Kemptown BLU

← Blog

Navigation mesh decoration display of koth_kemptown's RED spawn.

I find it hard to believe that it'd ever happen, but after a year and a half in limbo, Kemptown (KOTH) finally has bot support! Normally I'd just sneak this into the next round of patch notes, but it's a bit long for bullet point format.

For the longest time, RED bots would have trouble leaving their spawn room. On a listen server, tf_show_mesh_decoration would show that it was being treated as a BLU spawn room.

Navigation mesh decoration display of koth_kemptown's RED spawn.

Considering one of my goals is to provide a server that runs quality maps and lets players experience them even if no other players are available, this was a frustrating issue.

After poring over the entity list, nothing obvious stood out, func_respawnroom entities were the correct team. info_player_teamspawns had the appropriate team numbers for each team.

At the time, it was the only map that had this issue, and so, without any further leads, it was shelved.

September 2018: Enter Watergate

Since Kemptown was shelved, I learned a decent amount more about the inner workings of TF2. SDK calls. Detours. Reverse engineering. Writing toy extensions in C++.

With that, I started work on improving bots so they would be playable on other maps. Being able to inject replacement actions meant having more control than just persuading the game to take certain code paths (as with the current Payload Race support), so I figured Player Destruction would be simple enough. Just SeekAndDestroy on the bots and we should be good, right?

Right, except for Watergate. Watergate had the same issue. RED Bots eventually managed to get out of their spawn there, but it wasn't ideal (not to mention any BLU bots standing outside managed to force the RED bots into doing nothing).

Armed with the newfound experiecne and IDA, it was time to go back.

As it turns out, the determination of spawn room areas is handled by the function CTFNavMesh::DecorateNavMesh(), and in particular, it iterates over a ITFTeamSpawnAutoList interface to do so, checking the team numbers of the entities in that list. A quick reference finds that TFTeamSpawn refers to the info_player_teamspawn entity, so it was time to look over the spawn points again.

This one stood out:

"origin" "3206.79 501.754 -126.995"
"angles" "0 0 0"
"classname" "info_player_teamspawn"
"hammerid" "1903809"

In particular, it doesn't have a TeamNum key entry, nor a target name.

Where is this entity? Unsurprisingly:

Navigation mesh decoration display of koth_kemptown's RED spawn.

RED spawn.

In talking with a mapper, I discovered that these entities without teams assigned are supposedly used as a reference for the map scale and are probably left over from that process.

Why the TF2 developers decided to implement the code in a way that doesn't account for unassigned spawn points, I have no idea. But one quick batch of Stripper:Source configs later, and the bots are happy on both maps.

tl;dr Always have team numbers on your spawn points.

(Up you go!)