Toggleable trigger_push

Today we’re going to come up with a very handy base for a whole host of hacks, and demonstrate it with a trigger_push. The idea is to create a trigger which moves between two positions (using some of the func_door code to enable the movement). By having one of the positions be inside the map and one outside, we effectively have a trigger we can turn on or off by targetting it. The choice of trigger_push has some interesting interactions with this hack as well. Thanks to DeeDoubleU over at func_ for suggesting this challenge.

The entity listing we’re gonna make today follows. This should be a brush entity, positioned 128 units below where you want the trigger to appear (so build it in the “closed position” outside the map).

"use"		"door_use"
"state"		"1"
"spawnflags"	"36"
"pos2"		"0 0 128"
"speed"		"1000000"
"think"		"LinkDoors"
"nextthink"	"0.01"
"noise1"	"misc/null.wav"
"noise2"	"misc/null.wav"

"classname"	"InitTrigger"
"touch"		"trigger_push_touch"
"movedir"	"0.00001 0 0"
"targetname"	"togglepush"

The code divides into two halves – the bits which make the door work, and the bits that make the trigger_push work. In order of appearance, here’s what’s happening.

We start by setting our use function to be the one a door has. We set state to 1, because this is the state a door should have when it is at pos1 and about to move to pos2. Normally the func_door spawn function would set this, but we have to do it manually. We have set the spawnflags TOGGLE and DONT_LINK on the door with the value 36; the former prevents the trigger from automatically resetting. Our choice of pos2 makes the trigger move vertically 128 units when “opened”, this could be customised to suit your level. We set speed high enough that the trip takes under 0.1 seconds, as this means the trigger is instantly teleported by SUB_CalcMoveDone and so we don’t have to worry about movetypes.

Phew, so all the above is the strategic stuff. The next 4 settings are all firefighting to fix some bugs. It turns out that skipping the func_door can’t be fixed just by setting state, we also need the owner and enemy fields to be set on our door. Because these fields are references to entities, they’re awkward to set directly as a hack, so we employ the LinkDoors function to do the heavy lifting. This function does a lot of complicated stuff, but we don’t have to think about any of it if we set the DONT_LINK spawnflag, which is why we added it earlier. noise1/noise2 suppress missing sound errors.

The rest of the hack uses the tricks from Build Your Own Trigger to get a trigger like a trigger_push. The clever part is to overcome an overlap of fields: our door stuff already set speed really high to get teleportation to kick in, but speed also controls the push velocity! To avoid insanely fast pushing, the solution is to make movedir a much shorter vector than normal to compensate.

Phew, job done! I plan to revisit this idea shortly, because it has wider applications. However, it turns out trigger_push is particularly amenable to this trick in a way that e.g. trigger_hurt is not, so we’ll take that to a new article.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.