6 activator = self.enemy;
12 ==============================
15 the global "activator" should be set to the entity that initiated the firing.
17 If self.delay is set, a DelayedUse entity will be created that will actually
18 do the SUB_UseTargets after that many seconds have passed.
20 Centerprints any self.message to the activator.
22 Removes all entities with a targetname that match self.killtarget,
23 and removes them, so some events can remove other triggers.
25 Search for (string)targetname in all entities that
26 match (string)self.target and call their .use function
28 ==============================
30 void() SUB_UseTargets =
32 local entity t, stemp, otemp, act;
39 // create a temp object to fire at a later time
41 t.classname = "DelayedUse";
42 t.nextthink = time + self.delay;
45 t.message = self.message;
46 t.killtarget = self.killtarget;
47 t.target = self.target;
55 if (activator.classname == "player" && self.message != "")
57 centerprint (activator, self.message);
59 sound (activator, CHAN_VOICE, "misc/talk.wav", 1, ATTN_NORM);
63 // kill the killtagets
70 t = find (t, targetname, self.killtarget);
86 t = find (t, targetname, self.target);
108 void() trigger_reactivate =
110 self.solid = SOLID_TRIGGER;
113 //=============================================================================
115 float SPAWNFLAG_NOMESSAGE = 1;
116 float SPAWNFLAG_NOTOUCH = 1;
118 // the wait time has passed, so set back up for another activation
123 self.health = self.max_health;
124 self.takedamage = DAMAGE_YES;
125 self.solid = SOLID_BBOX;
130 // the trigger was just touched/killed/used
131 // self.enemy should be set to the activator so it can be held through a delay
132 // so wait for the delay time before firing
133 void() multi_trigger =
135 if (self.nextthink > time)
137 return; // allready been triggered
140 if (self.classname == "trigger_secret")
142 if (self.enemy.classname != "player")
144 found_secrets = found_secrets + 1;
145 WriteByte (MSG_ALL, SVC_FOUNDSECRET);
149 sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
151 // don't trigger again until reset
152 self.takedamage = DAMAGE_NO;
154 activator = self.enemy;
160 self.think = multi_wait;
161 self.nextthink = time + self.wait;
164 { // we can't just remove (self) here, because this is a touch function
165 // called wheil C code is looping through area links...
166 self.touch = SUB_Null;
168 self.nextthink = time + 0.1;
169 self.think = SUB_Remove;
175 self.enemy = activator;
181 if (other.classname != "player")
184 // if the trigger has an angles field, check player's facing direction
185 if (self.movedir != '0 0 0')
187 makevectors (other.angles);
188 if (v_forward * self.movedir < 0)
189 return; // not facing the right way
196 void multi_eventdamage (vector hitloc, float damage, entity inflictor, entity attacker, float deathtype)
198 if (!self.takedamage)
200 self.health = self.health - damage;
201 if (self.health <= 0)
203 self.enemy = attacker;
208 /*QUAKED trigger_multiple (.5 .5 .5) ? notouch
209 Variable sized repeatable trigger. Must be targeted at one or more entities. If "health" is set, the trigger must be killed to activate each time.
210 If "delay" is set, the trigger waits some time after activating before firing.
211 "wait" : Seconds between triggerings. (.2 default)
212 If notouch is set, the trigger is only fired by other entities, not by touching.
213 NOTOUCH has been obsoleted by trigger_relay!
219 set "message" to text string
221 void() trigger_multiple =
223 if (self.sounds == 1)
225 precache_sound ("misc/secret.wav");
226 self.noise = "misc/secret.wav";
228 else if (self.sounds == 2)
230 precache_sound ("misc/talk.wav");
231 self.noise = "misc/talk.wav";
233 else if (self.sounds == 3)
235 precache_sound ("misc/trigger1.wav");
236 self.noise = "misc/trigger1.wav";
241 self.use = multi_use;
247 if (self.spawnflags & SPAWNFLAG_NOTOUCH)
248 objerror ("health and notouch don't make sense\n");
249 self.max_health = self.health;
250 self.event_damage = multi_eventdamage;
251 self.takedamage = DAMAGE_YES;
252 self.solid = SOLID_BBOX;
253 setorigin (self, self.origin); // make sure it links into the world
257 if ( !(self.spawnflags & SPAWNFLAG_NOTOUCH) )
259 self.touch = multi_touch;
265 /*QUAKED trigger_once (.5 .5 .5) ? notouch
266 Variable sized trigger. Triggers once, then removes itself. You must set the key "target" to the name of another object in the level that has a matching
267 "targetname". If "health" is set, the trigger must be killed to activate.
268 If notouch is set, the trigger is only fired by other entities, not by touching.
269 if "killtarget" is set, any objects that have a matching "target" will be removed when the trigger is fired.
270 if "angle" is set, the trigger will only fire when someone is facing the direction of the angle. Use "360" for an angle of 0.
276 set "message" to text string
278 void() trigger_once =
284 //=============================================================================
286 /*QUAKED trigger_relay (.5 .5 .5) (-8 -8 -8) (8 8 8)
287 This fixed size trigger cannot be touched, it can only be fired by other events. It can contain killtargets, targets, delays, and messages.
289 void() trigger_relay =
291 self.use = SUB_UseTargets;
295 //=============================================================================
300 self.count = self.count - 1;
306 if (activator.classname == "player"
307 && (self.spawnflags & SPAWNFLAG_NOMESSAGE) == 0)
310 centerprint (activator, "There are more to go...");
311 else if (self.count == 3)
312 centerprint (activator, "Only 3 more to go...");
313 else if (self.count == 2)
314 centerprint (activator, "Only 2 more to go...");
316 centerprint (activator, "Only 1 more to go...");
321 if (activator.classname == "player"
322 && (self.spawnflags & SPAWNFLAG_NOMESSAGE) == 0)
323 centerprint(activator, "Sequence completed!");
324 self.enemy = activator;
328 /*QUAKED trigger_counter (.5 .5 .5) ? nomessage
329 Acts as an intermediary for an action that takes multiple inputs.
331 If nomessage is not set, t will print "1 more.. " etc when triggered and "sequence complete" when finished.
333 After the counter has been triggered "count" times (default 2), it will fire all of it's targets and remove itself.
335 void() trigger_counter =
341 self.use = counter_use;
344 .float triggerhurttime;
348 if (other.items & IT_KEY1 || other.items & IT_KEY2)
349 other.pain_finished = time + 2;
351 if (other.takedamage)
352 if (other.triggerhurttime < time)
354 other.triggerhurttime = time + 1;
355 Damage (other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
361 /*QUAKED trigger_hurt (.5 .5 .5) ?
362 Any object touching this will be hurt
363 set dmg to damage amount
366 void() trigger_hurt =
369 self.touch = hurt_touch;
373 self.message = "was in the wrong place.";
376 //void() target_speaker_use = {sound(self, CHAN_VOICE, self.noise, 1, 1);}
377 //void() target_speaker = {self.use = target_speaker_use;}
379 void() target_speaker =
382 precache_sound (self.noise);
383 ambientsound (self.origin, self.noise, 1, ATTN_STATIC);
392 self.nextthink = time + 0.1;
394 if(random() < self.wait) {
395 te_spark(self.origin,'0 0 -1',self.cnt);
402 self.think = sparksthink;
403 self.nextthink = time + 0.2;
405 // self.cnt is the amount of sparks that one burst will spawn
407 self.cnt = 25.0; // nice default value
410 // self.wait is the probability that a sparkthink will spawn a spark shower
411 // range: 0 - 1, but 0 makes little sense, so...
412 if(self.wait < 0.05) {
413 self.wait = 0.25; // nice default value
418 precache_sound (self.noise);
419 ambientsound (self.origin, self.noise, 1, ATTN_STATIC);