TF2 Classic is coming to Steam!
February 25, 2025 - bobatealee
Tags:
announcement
development

TF2 Classic is coming to Steam in 2025!
"Steam" is a mysterious resource created when coal is burned in certain situations — a harrowing thought to coal-lovers like the Civilian, to whom burning coal is like setting one's own children on fire. But maybe a foray into the Steam industry is just what the company needs to capture new eyes.While porting efforts are underway, click here to wishlist!
Playing With Fire: Flame Where You Aim
October 13, 2024 - Nitoandthefunkybunch
Tags:
development
fun
Many experienced Pyro players coming into TF2 Classic have reported flames feeling off. This is often chalked up to the flames in TF2 Classic being slower than their Live TF2 counterparts, and it's true that they are. There is way more going on behind the scenes, however. When you are moving and shooting, flames will inherit your velocity; if you move forward/backward, they will move faster/slower. While this does not increase or decrease your range, it also means that moving to the side causes your flames to move to the side. They veer off course, which results in situations like the following:
Fixing this serverside was easy: you simply calculate a relative velocity in the direction the Pyro is looking. For the client this is a much trickier issue. Source particles are handled at an engine level, which we don't have access to, and there is no existing function to calculate the relative velocity. This also means we have no easy way to line the flames up with the hitboxes directly, like in Live TF2.
We had to get a bit creative, and after pursuing several options (one of which involved a floating nail that would send its speed to the flames), we discovered that if we simply edit a set of coordinates every frame, and send that to the particle, then the particle can treat it as a velocity value and send the flames in the correct direction. So, in Update 2.2, flames will have new physics that reward leading your shots and sporadic movement. Here is a diagram of the difference:
That's all for this series of posts! Don't worry—you'll be hearing from us again soon!

Fixing this serverside was easy: you simply calculate a relative velocity in the direction the Pyro is looking. For the client this is a much trickier issue. Source particles are handled at an engine level, which we don't have access to, and there is no existing function to calculate the relative velocity. This also means we have no easy way to line the flames up with the hitboxes directly, like in Live TF2.
We had to get a bit creative, and after pursuing several options (one of which involved a floating nail that would send its speed to the flames), we discovered that if we simply edit a set of coordinates every frame, and send that to the particle, then the particle can treat it as a velocity value and send the flames in the correct direction. So, in Update 2.2, flames will have new physics that reward leading your shots and sporadic movement. Here is a diagram of the difference:

That's all for this series of posts! Don't worry—you'll be hearing from us again soon!
Playing with Fire: The Dreaded Invisible Flames
October 13, 2024 - Nitoandthefunkybunch
Tags:
development
Yes, those invisible flames. This notorious bug has been finally been fixed in Update 2.2! The reason this bug had taken so long to fix was due to a roadblock: nobody knew how to reproduce it. Without a way to test, we could only make assumptions when attempting to fix it, only to find out days later that it didn't work.
It turns out there were not just one, but two invisible flame bugs, and both have to do with networking. In simple terms, the client would disagree with the server on whether the Flamethrower was actually firing. The server would still properly shoot flames, but the client wouldn't show the particle.
The first, more uncommon cause was the weapon state. In Source Engine games, there are a series of states that determine what animation your weapon plays. A weapon in the 'IDLE' state will do nothing, and a weapon in the 'FIRING' state will play a firing animation. To prevent desync, the server will send the client a message if this changes, and vice versa. In certain rare scenarios, such as the particle system restarting, the client would think that your Flamethrower is in the 'IDLE' state. The server stays in the 'FIRING' state, and, since it doesn't change, would not notify the client. The solution is to have the 'FIRING' state actually cycle between two states: 'FIRING' and 'FIRING_VERIFY', which means it is constantly being conveyed to the client.
The second, much more common occurrence, was due to the client believing the enemy's Flamethrower did not have any ammo. For reasons that we do not fully understand, this value would somehow not get networked to the client. The game will check if the Flamethrower has enough ammo to fire before starting the fire effects, so they would not be rendered. This check, however, appears to be redundant. You cannot hold a Flamethrower if it has no ammo, so we simply removed the check.
Stay tuned for our final post on the subject tomorrow!
It turns out there were not just one, but two invisible flame bugs, and both have to do with networking. In simple terms, the client would disagree with the server on whether the Flamethrower was actually firing. The server would still properly shoot flames, but the client wouldn't show the particle.
The first, more uncommon cause was the weapon state. In Source Engine games, there are a series of states that determine what animation your weapon plays. A weapon in the 'IDLE' state will do nothing, and a weapon in the 'FIRING' state will play a firing animation. To prevent desync, the server will send the client a message if this changes, and vice versa. In certain rare scenarios, such as the particle system restarting, the client would think that your Flamethrower is in the 'IDLE' state. The server stays in the 'FIRING' state, and, since it doesn't change, would not notify the client. The solution is to have the 'FIRING' state actually cycle between two states: 'FIRING' and 'FIRING_VERIFY', which means it is constantly being conveyed to the client.
The second, much more common occurrence, was due to the client believing the enemy's Flamethrower did not have any ammo. For reasons that we do not fully understand, this value would somehow not get networked to the client. The game will check if the Flamethrower has enough ammo to fire before starting the fire effects, so they would not be rendered. This check, however, appears to be redundant. You cannot hold a Flamethrower if it has no ammo, so we simply removed the check.
Stay tuned for our final post on the subject tomorrow!