The story so far…
In the early days we created a delayed spawn trigger_once. Our quest will not be over until we can create a trigger_multiple which is toggled on and off when triggered. Today we will get closer, read on…
Today we aim to create a
trigger_once which can be “respawned”; although it initially fires just once when touched, we can
use the trigger after it has fired to make it live again for one more touch. It will be possible to respawn it in this way an unlimited number of times. This hack builds on the ideas of the Build Your Own Trigger article, so I recommend you read that first, or revisit it as a reminder.
The hack begins with a “
trigger_once” made using the method in the article above. Create an brush entity with the following fields
"classname" "InitTrigger" "touch" "multi_touch" "message" "test message"
If you touch this trigger, it will fire the message once then disappear (the entity is completely removed). As usual in this kind of hack, the slightly weird way of creating a standard entity lets us override any fields we like, in a way the standard spawn function would block. For testing purposes we’re just printing a message, but setting a
target would work as usual.
Quick spot of theory. When a
trigger_multiple fires, there is a waiting period (controlled by
wait) before the trigger can be touched again. How does the QuakeC enforce this? There are several options I’d consider if I had to write it: setting the
solid type to
SOLID_NOT, clearing the collision model, moving the entity out of range. In fact standard Quake code does something else – it just checks if the entity’s
nextthink time is in the future each time a collision occurs, and if so it doesn’t act on the collision.
It’s a bit strange that rather than turning off the collisions, it continues to let them happen but just disconnects the relay. One thing to realise is that all of the alternatives I suggested need a
think function and a
nextthink time to undo the change, so you may as well just detect that the
nextthink is still pending and avoid having to destroy and recreate the setup of the entity. Knowing that this is what’s going on behind the scenes is key to today’s hack.
We only have to add one key to our trigger to turn it from
wait. Set this to 3 and the test message will loop while you stand inside the trigger. If you change it again to
wait 999999999999, you seem to have got the worst of both worlds: your trigger will in effect never get around to resetting, so it has the same effect as a
trigger_once would, but the entity is never removed either.
Add the following fields, and everything changes
"use" "hurt_on" "targetname" "reboot"
hurt_on performs two functions, setting
SOLID_TRIGGER and setting
-1. We’re using it for the latter effect here, since we know changing
nextthink is the only thing needed to reactivate a trigger. Add a button with
"target" "reboot", and you will have a
trigger_once that reactivates on demand.
One enhancement that might be needed is for the trigger to start inactive, and only begin detecting collisions after being activated. This is relatively simple, we just need to find a function which will set a
nextthink very far in the future, and have it run as soon as the entity spawns.
door_go_up will fit the bill, so long as we are in
STATE_UP in door terms. Luckily that is
state 0, so we don’t need to set an extra key. Add the following to the trigger.
"think" "door_go_up" "nextthink" "0.05"
One warning about this entity we’ve created, it’s a bit of a landmine! We have a function to deploy the mine, but once it’s deployed there’s no way to go near without setting it off. In less dramatic terms, there’s no way to restore the trigger, then change your mind before it is set off and disable it again for a while. The nuclear option of using
killtarget to remove the entity completely will work of course, but that’s a permanent removal. I haven’t found a tweak that adds this feature yet, but if you can come up with one post a comment below.
I have more to say on this entity setup, but I like to keep the map hack posts shorter, so I’ll post a follow-up later. You can download the test map bleeptest to try out the hack (.map and .bsp included). There is a trigger in the pit at the end of the corridor which begins inactive. Hit the button behind you to activate it, then jump in to trigger the message, and repeat as many times as you like!