There is no spoon
Legacy:Trigger
- Verb Definition: see Triggered
When a Trigger is touched by a valid object, usually a Player or some other type of Pawn, it causes a certain event to be initiated. However, if a Trigger is listening for an event and detects it, then it is turned on or off according to its state and whether it was on or off to begin with.
The event that a Trigger calls is Events -> Event and the event it listens for is Events -> Tag, both under the Events section of the properties. The Event page explains this in more depth.
Even though this is a very simple thing for an actor to do, there are many variables that are used to alter the way this is done.
Contents
Tips
To see where triggers are so you can easily test them in game:
- Change their Lighting properties so they cast a small circle of light: set LightType, LightRadius and LightBrightness. See Actor (UT)/Lighting for more info on these properties.
- Alternatively, you can set Advanced -> bHidden to false, this will display the trigger icon from UEd ingame.
- Use SHOWALL command in console.
Properties
- bool bInitiallyActive
- This variable determines whether the trigger is on or off when the level starts. A Trigger can be put to sleep or woken up by being triggered itself: see the States section below.
- bool bTriggerOnceOnly
- If this variable is set to True, then the trigger will function once. If it is set to False, then the Trigger will work over and over again, as long as the Trigger is left active.
Wild guess: if this is set to true, it can't be subsequently woken up by triggering. I'm guessing the script just send it to the None state →Tarquin - ETriggerType TriggerType
- The content of this variable is used to determine exactly what kind of actors are relevant, i.e. what actors will make this Trigger work when they touch it. This is an enumerator, and here are its choices:
- |TT_PlayerProximity| This trigger can only be set off by a PlayerPawn.
- |TT_PawnProximity| This trigger can be set off by any type of Pawn (UT).
- |TT_ClassProximity| This trigger can only be set off by Actors of a certain class or Actors of a class below this one. (So if you make a Trigger that only a Nali can set off, then a Nali Priest will also be able to set it off.) The class that is capable of setting off this trigger is defined in the ClassProximityType variable.
- |TT_AnyProximity| This trigger can be set off by pretty much anything touching it other than the world geometry. Use caution when selecting this option.
- |TT_Shoot| This trigger is set off by being shot and damaged. To be successfully set off, the Trigger must sustain at least as much damage as is specified in the DamageThreshold variable.
- |TT_HumanPlayerProximity (only UT2003/4)| Trigger activated by human player (not bot)
- |TT_LivePlayerProximity (only UT2004)| Trigger only activated by live player, untriggered if player dies while touching
- class<Actor> ClassProximityType
- This property determines what classes are capable of setting off this Trigger. It is only relevant if the TriggerType variable is set to TT_ClassProximity.
- float DamageThreshold
- This property determines how much damage is necessary to successfully set off. It is only relevant if the TriggerType variable is set to TT_Shoot.
- float ReTriggerDelay
- After each time the Trigger is successfuly activated, it is prevented from doing so again until this length of time has elapsed. This property doesn't interfere with RepeatTriggerTime, since it is dependant on the Trigger being deactivated (or UnTriggered).
- float RepeatTriggerTime
- This property is inactive if set to 0. If the actor setting off the Trigger remains within the Trigger's proximity, then the Trigger will be set off over and over again at this interval until the actor leaves the Trigger's proximity. SuperApe: I've noticed that Triggers will indeed repeat (only a couple times) even if this property is zero.
- string Message (localized)
- If a Player is the reason that a Trigger is successfully set off, either because the player touched the Trigger or shot it, then this message will be sent to that player through his console. The message is displayed in the same place as incoming talk messages. If you want to use a trigger to display a bigger message, you'll need to make a subclass of Trigger which, instead of using that dinky Message text, have the player receive a LocalMessage containing your text. They could all be stored in MyLevel to eliminate the need for an additional package.
CollisionHeight and CollisionRadius
These properties (under the Collision grouping) determine the size of the Trigger's collision cylinder.
Even though all Actors have these variables in their Collision properties, it is important to remember that they can be adjusted by the mapper to allow for different dimensions where collision should be checked. This is useful so that a mapper can use a single Trigger to cover a large area, or to cover an area that requires pinpoint accuracy from a player.
In UnrealEngine2 and later, you can also use static meshes for triggers. In this instance, the static meshes collision properties will be used instead of the cylindrical collision height and radius.
Foxpaw: Can someone with UT2004 check to see if the same holds true for meshes (skeletal/vertex animated) with special collision hulls as well?
bHidden
If you want to make the trigger up while playing, for example, if you made a fancy arrow for it to tell the player where to shoot, you cannot simply set bHidden to false. In the code, it is made to set its DrawType to None which means whenever you load up a level with your trigger in it, it will never show up.
States
The Object -> InitialState property contains a list of states that are made available to mappers.
The Trigger class does not switch states during gameplay. The different states determine how the trigger behaves when it is itself triggered (by another Trigger, for example). These allow the Trigger to be woken up or put to sleep.
- None
- The Trigger is in a permanently inactive state. The None state exists for all actors, otherwise it would not be here. Ignore this state. (Actually, doesn't this behave the same as NormalTrigger?)
- NormalTrigger
- The Trigger is permanently active and can't be turned off.
- OtherTriggerTurnsOff
- If the Trigger itself is triggered, then it will be permanently deactivated. Note that bInitiallyActive must be set to true, otherwise the trigger will be off and will stay off when triggered.
- OtherTriggerTurnsOn
- If the Trigger itself is triggered, then it will be permanently activated. Again if bInitiallyActive is true then it will be on already when triggered.
- OtherTriggerToggles
- If the Trigger itself is triggered, it will be turned off if it was on, and vice versa. This is repeatable.
Known subclasses in UT
Known Subclasses in UT200x
- TeamTrigger
- ZoneTrigger
- RandomTrigger (custom)
- RotationalTriggering (custom)
- ComboTrigger (custom)
Related Topics
- Dynamics - Main topic page for triggers & sounds.
- Types of Trigger - Summary of trigger types.
- Trigger Systems - Examples and concepts on complex systems using triggers and triggerable actors.
Discussion
Legal: Quick Q: How do I make one ElevatorTrigger to trigger 2 events? I need them both to be triggered in the Event> Event... :(
Tarquin: Trigger a Dispatcher. And have you edited this page text in MS Word? some ' characters have been turned into Evil Entities :)
Legal: Nope, sorry, wish I had ;) Anyway, the problem is that I have to trigger an ElevatorTrigger with an ElevatorTrigger... :/ But it doesn't work with a Dispatcher. So, I have to either A; Trigger 2 events with one ElevatorTrigger, or B; Find a workaround.
The workaround I have is to add an attachmover to move the first ElevatorTriggers away, but I'd like to avoid more movers.
Tarquin: Ah. Hm. Move this discussion to ElevatorTrigger. I think the on ly thing to do is subclass & rewrite the bad code
Tarquin: WHy can't both the ElevatorMovers have the same Tag? If not, subclass and put:
var(Events) AuxEvent; function Touch( actor Other ) { local ElevatorMover EM; if( IsRelevant( Other ) ) { // Call the ElevatorMover's Move function if( AuxEvent != '' ) foreach AllActors( class 'ElevatorMover', EM, AuxEvent) EM.MoveKeyframe( GotoKeyFrame, MoveTime ); if( bTriggerOnceOnly ) // Ignore future touches. SetCollision(False); } super.Touch( Other ); }
Legal: Sorry, can't move now, tomorrow. Anyway, thanks for the code, now how do I add this mover? (The command line) I need it to make a door be opened from one side, but still I need to blow it from any side. It all works, or it should, I think. In a hurry, bye.
Tarquin: that's an ElevatorTrigger subclass ....
MythOpus: Trigger Type Shoot doesn't seem to work for me at all anymore :S
Dr.AwkwArD: do we really want to do double duty like this? UT and UT2003 info on the same page? If so (which I'm not sure I support), we must be extremely clear about which info is universal (and through which engine/game). Frankly, I'd like to see this page broken into separate pages under the umbrellas UT and UT2003 for their respective class info – even if some/much of the info will be redundant.
Tarquin: Are there any differences in the properties? I thought they were identical
Wormbo: There's nothing wrong with keeping them on the same page. UT2003 and UT2004 only add an item to the ETriggerType enum.
SuperApe: I agree with Wormbo. There may have been big differences in code between UT and 2k3 (I really can't say), but 2k4 simply appends some code (and changes very little exhisting code). With that in mind, that's why I began to speak up on the Triggers page, but I didn't elaborate; my bad. Without large changes in the engine, I would kinda hope the 2k3 structure we had would remain the way it was. Not only do other pages on the Wiki refer to wiki pages by Title, but links off-site do too. Btw, I have begun a short (short) thread on a Forum listing the missing or disabled things in 2k4 from 2k3. That might be worth listing on the Wiki somewhere. Differences between 2k3 and 2k4.
Shuggyboy: I want a mover(lift) to be called to the upper level when a player/bot approaches the edge. at the moment the lifts remain at the ground level and its a long way down. I have tried looking through the trigger and mover tutorials but cant seem to find the correct way to implement changing the keynum on the mover from 0 to 1 when the player/bot approaches. Any ideas?
Foogod: What you will probably need to do is set the mover's Object->InitialState to TriggerOpenTimed, and then create a trigger at the top to trigger it to move when the player comes close enough. Note, however, that this means that it won't move by default anymore when somebody stands on it at the bottom. If you want it to do that too, you will need to set a trigger which detects somebody standing on it at the bottom as well. Depending on your architecture, you may be able to set the collision area so that the same trigger covers the right areas at both the bottom and the top of the lift, which would be ideal (using Collision->bUseCylinderCollision). If you can't do that, you will probably need to do some fiddling with things so that the bottom trigger doesn't make the lift move again when the person riding it is travelling down and gets to the bottom (otherwise it'll just keep bouncing). The best way to do this is probably to make the bottom-trigger active only when the lift is at the bottom (by making the lift's MoverEvent->OpeningEvent and MoverEvent->ClosedEvent turn the trigger off and on). Alternately, you might also be able to just make the bottom-trigger move with the lift (see Attaching Actors).
SuperApe: This page needs a proper subclass tree, once it's made into a proper class page.
SuperApe: I am trying to use a Trigger set to ClassProximity and ProximityClassType set to 'Monster'. For some reason, this is not working properly. It does not detect this xPawn subclass. I don't have the code in front of me atm, but earlier I remembered seeing specific checks within a ClassProximity setting to see if Pawns are Player controlled or something like that. Anyone else seeing this problem? Anyone see the cause, a solution or workaround?
SuperApe: Update to previously mentioned problem: Monsters are considered Players by the code in this class because of the bIsPlayer boolean in MonsterController. They have been set like this simply to allow Monsters to ride lifts when standing on them.
VerteX Hey Super Ape, if u need it to trigger 2 events, just set the elevator's event to trigger a scripted trigger that triggers thou other two events. wouldn't that work?
SuperApe: I think it would, but I didn't have that problem. :p Not sure who's problem you're addressing.