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
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
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.
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.