In my TF2 king of the hill map koth_skylab, I wanted an ending sequence that would use a trigger to set the losing team on fire.
The usual way of distinguishing between teams in a trigger is to use a filter_activator_tfteam. It has a Team property which can be set to the red team or blue team. Spawn room doors are a typical use of this filter, to allow only Red players into the Red spawn room, and only Blue players into the Blu spawn room.
An alternative property, Associated Control Point, allows the filter to allow only playersfrom whichver team owns a particular control point. A trigger using this filter, connected to a door, would only open the door for Red players if Red had captured the control point, and similarly for Blue if Blue owned the point. If the control point was neutral, the door would open for nobody.
Finding the winners
In a king of the hill map, there is a single control point. Each team must try to hold the point for as long as possible. A team wins when they have held the control point cumulatively for a certain time; e.g. three minutes. Consequently, you can identify the winning team as the team that owns the control point when the round finishes. The winning team then gets ten seconds or so—the “humiliation period”—in which to slaughter the losers.
When the Red team wins a round, the tf_gamerules entity sends the OnWonByTeam1 output; when Blue wins, it sends the OnWonByTeam2 output. If you have a trigger, filtered by the control point, that is initially disabled, and then enable it when either team wins, only the winning players will activate the trigger.
I don’t really want to set the winners on fire—it would be a strange reward for winning—but I’ll add the logic here so you can see how it works. When the trigger gets an OnStartTouch input, it sends the IgnitePlayer output to !activator, which is the special identifier for “the entity that sent the input”, which in this case will be any player matching the filter. Hammer may not recognise these options, and will display them in red, but they will work just fine in the game.
Finding the losers?
Finding the losers should be easy. The third property on filter_activator_tfteam is Filter Mode. Set this to Disallow, and instead of allowing the matching team to activate the trigger, the filter will disallow them, and allow every other player to activate it. The team-filtered door in the second example above would open for both teams when nobody owned the point, for the Red team when Blue owned the point, and for the Blue team when Red owned the point. For pyromaniacs, the trigger shown below will set the entire losing team in the trigger area on fire.
However, there is a catch. If you enable this trigger during the round, it will work exactly as expected: the team that owns the point will be unaffected, and the team that doesn’t own it will burn. But if the trigger is enabled in the humiliation period after the round ends, both teams catch fire.
It turns out that for the duration of the humiliation period, all team-based filters will always match the winning team. This is so that the winning Blu team can open the spawn room doors of the losing Red team (or vice-versa), to slaughter any cowardly players trying to hide in it—a worthy cause, indeed.
But it causes me a little problem: although I can identify the winners, those-who-own-the-control-point, the inverted logic those-who-don’t-own-the-control-point that should identify the losers also matches the winners. It’s incredibly funny when both teams catch fire, but it’s not quite what I want.
All is not lost
I can still identify the losers, and only the losers, but those-who-don’t-own-the-control-point isn’t good enough because of the peculiar behaviour of filter_activator_tfteam after the round. What I need is to take the effect of the winning team filter (which still only matches the winners after the round ends) and invert its logic in some other way.
There’s another filter entity in Source, filter_multi, which allows you to create complex filters by performing logical operations on several other filters that you specify. If you set its Logic Type property to AND, it will pass only if all the other filters pass; set it to OR, and it will pass if any one of the other filters pass. I don’t need that capability here, but filter_multi also has a Negate Outcome property, which turns what would be a pass into a fail, and vice-versa.
What this means is that the output of the filter_multi is not affected by team logic or humiliation periods at all, but only by the outputs of the other filters it specifies. So although the Filter Mode property of the filter_activator_tfteam turned out to be unsuitable, if I use a winning team filter and send its output through a negated filter_multi, it will match only the losing team.
There’s one small issue remaining with our trigger and filter set up: the filter_activator_tfteam matches all players on the winning team, and so the filter_multi, being negated, matches everything else. Not just players, but all other entities. The fix for this is easy: just ensure the trigger flags are set to just Clients.