]> icculus.org git repositories - divverent/nexuiz.git/blob - TeamNexuiz/game/gamec/g_triggers.c
- Fixed Triggers to work properly with TF maps (one entity needs a function though..)
[divverent/nexuiz.git] / TeamNexuiz / game / gamec / g_triggers.c
1 // Move to tfdefs:\r
2 entity damage_attacker;                 // ADD FUNCTION FOR\r
3 \r
4 void() SUB_UseTargets;\r
5 \r
6 void() DelayThink =\r
7 {\r
8         activator = self.enemy;\r
9         SUB_UseTargets ();\r
10         remove(self);\r
11 };\r
12 \r
13 /*\r
14 ==============================\r
15 SUB_UseTargets\r
16 \r
17 the global "activator" should be set to the entity that initiated the firing.\r
18 \r
19 If self.delay is set, a DelayedUse entity will be created that will actually\r
20 do the SUB_UseTargets after that many seconds have passed.\r
21 \r
22 Centerprints any self.message to the activator.\r
23 \r
24 Removes all entities with a targetname that match self.killtarget,\r
25 and removes them, so some events can remove other triggers.\r
26 \r
27 Search for (string)targetname in all entities that\r
28 match (string)self.target and call their .use function\r
29 \r
30 ==============================\r
31 */\r
32 /*void() SUB_UseTargets =\r
33 {\r
34         local entity t, stemp, otemp, act;\r
35 \r
36 //\r
37 // check for a delay\r
38 //\r
39         if (self.delay)\r
40         {\r
41         // create a temp object to fire at a later time\r
42                 t = spawn();\r
43                 t.classname = "DelayedUse";\r
44                 t.nextthink = time + self.delay;\r
45                 t.think = DelayThink;\r
46                 t.enemy = activator;\r
47                 t.message = self.message;\r
48                 t.killtarget = self.killtarget;\r
49                 t.target = self.target;\r
50                 return;\r
51         }\r
52 \r
53 \r
54 //\r
55 // print the message\r
56 //\r
57         if (activator.classname == "player" && self.message != "")\r
58         {\r
59                 centerprint (activator, self.message);\r
60                 if (!self.noise)\r
61                         sound (activator, CHAN_VOICE, "misc/talk.wav", 1, ATTN_NORM);\r
62         }\r
63 \r
64 //\r
65 // kill the killtagets\r
66 //\r
67         if (self.killtarget)\r
68         {\r
69                 t = world;\r
70                 do\r
71                 {\r
72                         t = find (t, targetname, self.killtarget);\r
73                         if (!t)\r
74                                 return;\r
75                         remove (t);\r
76                 } while ( 1 );\r
77         }\r
78 \r
79 //\r
80 // fire targets\r
81 //\r
82         if (self.target)\r
83         {\r
84                 act = activator;\r
85                 t = world;\r
86                 do\r
87                 {\r
88                         t = find (t, targetname, self.target);\r
89                         if (!t)\r
90                         {\r
91                                 return;\r
92                         }\r
93                         stemp = self;\r
94                         otemp = other;\r
95                         self = t;\r
96                         other = stemp;\r
97                         if (self.use)\r
98                                 self.use ();\r
99                         self = stemp;\r
100                         other = otemp;\r
101                         activator = act;\r
102                 } while ( 1 );\r
103         }\r
104 \r
105 \r
106 };*/\r
107 \r
108 \r
109 \r
110 void() trigger_reactivate =\r
111 {\r
112         self.solid = SOLID_TRIGGER;\r
113 };\r
114 \r
115 //=============================================================================\r
116 \r
117 float   SPAWNFLAG_NOMESSAGE = 1;\r
118 float   SPAWNFLAG_NOTOUCH = 1;\r
119 \r
120 // the wait time has passed, so set back up for another activation\r
121 void() multi_wait =\r
122 {\r
123         if (self.max_health)\r
124         {\r
125                 self.health = self.max_health;\r
126                 self.takedamage = DAMAGE_YES;\r
127                 self.solid = SOLID_BBOX;\r
128         }\r
129 };\r
130 \r
131 \r
132 // the trigger was just touched/killed/used\r
133 // self.enemy should be set to the activator so it can be held through a delay\r
134 // so wait for the delay time before firing\r
135 /*void() multi_trigger =\r
136 {\r
137         if (self.nextthink > time)\r
138         {\r
139                 return;         // allready been triggered\r
140         }\r
141 \r
142         if (self.classname == "trigger_secret")\r
143         {\r
144                 if (self.enemy.classname != "player")\r
145                         return;\r
146                 found_secrets = found_secrets + 1;\r
147                 WriteByte (MSG_ALL, SVC_FOUNDSECRET);\r
148         }\r
149 \r
150         if (self.noise)\r
151                 sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);\r
152 \r
153 // don't trigger again until reset\r
154         self.takedamage = DAMAGE_NO;\r
155 \r
156         activator = self.enemy;\r
157 \r
158         SUB_UseTargets();\r
159 \r
160         if (self.wait > 0)\r
161         {\r
162                 self.think = multi_wait;\r
163                 self.nextthink = time + self.wait;\r
164         }\r
165         else\r
166         {       // we can't just remove (self) here, because this is a touch function\r
167                 // called wheil C code is looping through area links...\r
168                 self.touch = SUB_Null;\r
169 \r
170                 self.nextthink = time + 0.1;\r
171                 self.think = SUB_Remove;\r
172         }\r
173 };*/\r
174 \r
175 void() multi_trigger = \r
176 {\r
177         if (self.nextthink > time)\r
178         {\r
179                 return;\r
180         }\r
181         if (self.classname == "trigger_secret")\r
182         {\r
183                 if (self.enemy.classname != "player")\r
184                 {\r
185                         return;\r
186                 }\r
187                 found_secrets = found_secrets + TF_FLARE_OFF;\r
188                 WriteByte(2, 28);\r
189         }\r
190         if (self.noise)\r
191         {\r
192                 sound(self, 2, self.noise, TF_FLARE_OFF, TF_FLARE_OFF);\r
193         }\r
194         self.takedamage = TF_FLARE_LIT;\r
195         activator = self.enemy;\r
196         SUB_UseTargets();\r
197         if (self.wait > TF_FLARE_LIT)\r
198         {\r
199                 self.think = multi_wait;\r
200                 self.nextthink = time + self.wait;\r
201         }\r
202         else\r
203         {\r
204                 self.touch = SUB_Null;\r
205                 self.nextthink = time + 0.1;\r
206                 self.think = SUB_Remove;\r
207         }\r
208 };\r
209 \r
210 void() multi_killed = \r
211 {\r
212         self.enemy = damage_attacker;\r
213         multi_trigger();\r
214 };\r
215 \r
216 void() multi_use =\r
217 {\r
218         self.enemy = activator;\r
219         multi_trigger();\r
220 };\r
221 \r
222 void() multi_touch = \r
223 {\r
224         local entity te;\r
225         if (other.classname != "player")\r
226         {\r
227                 return;\r
228         }\r
229         if (other.is_dead == 1)\r
230                 return;\r
231         if (!Activated(self, other))\r
232         {\r
233                 if (self.else_goal != TF_FLARE_LIT)\r
234                 {\r
235                         te = Findgoal(self.else_goal);\r
236                         if (te)\r
237                         {\r
238                                 DoResults(te, other, self.goal_result & 2);\r
239                         }\r
240                 }\r
241                 return;\r
242         }\r
243 // if the trigger has an angles field, check player's facing direction\r
244         if (self.movedir != '0 0 0')\r
245         {\r
246                 makevectors (other.angles);\r
247                 if (v_forward * self.movedir < 0)\r
248                         return;         // not facing the right way\r
249         }\r
250 \r
251         self.enemy = other;\r
252         multi_trigger();\r
253 };\r
254 \r
255 void multi_eventdamage (vector hitloc, float damage, entity inflictor, entity attacker, float deathtype)\r
256 {\r
257         if (!self.takedamage)\r
258                 return;\r
259         self.health = self.health - damage;\r
260         if (self.health <= 0)\r
261         {\r
262                 self.enemy = attacker;\r
263                 multi_trigger();\r
264         }\r
265 }\r
266 \r
267 /*QUAKED trigger_multiple (.5 .5 .5) ? notouch\r
268 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.\r
269 If "delay" is set, the trigger waits some time after activating before firing.\r
270 "wait" : Seconds between triggerings. (.2 default)\r
271 If notouch is set, the trigger is only fired by other entities, not by touching.\r
272 NOTOUCH has been obsoleted by trigger_relay!\r
273 sounds\r
274 1)      secret\r
275 2)      beep beep\r
276 3)      large switch\r
277 4)\r
278 set "message" to text string\r
279 */\r
280 void (float tno) ConvertToGoal;\r
281 void () CheckIfQ3FTrigger;\r
282 void() trigger_multiple =\r
283 {\r
284 /*      if (CheckIfQ3FTrigger() == 1)\r
285         {\r
286                 ConvertToGoal (1);\r
287                 return;\r
288         }\r
289         if (CheckIfQ3FTrigger() == 2)\r
290         {\r
291                 ConvertToGoal (2);\r
292                 return;\r
293         }*/\r
294         CheckIfQ3FTrigger ();\r
295 \r
296         if (self.sounds == 1)\r
297         {\r
298                 precache_sound ("misc/secret.wav");\r
299                 self.noise = "misc/secret.wav";\r
300         }\r
301         else if (self.sounds == 2)\r
302         {\r
303                 precache_sound ("misc/talk.wav");\r
304                 self.noise = "misc/talk.wav";\r
305         }\r
306         else if (self.sounds == 3)\r
307         {\r
308                 precache_sound ("misc/trigger1.wav");\r
309                 self.noise = "misc/trigger1.wav";\r
310         }\r
311 \r
312         if (!self.wait)\r
313                 self.wait = 0.2;\r
314         self.use = multi_use;\r
315 \r
316         InitTrigger ();\r
317 \r
318         if (self.health)\r
319         {\r
320                 if (self.spawnflags & SPAWNFLAG_NOTOUCH)\r
321                         objerror ("health and notouch don't make sense\n");\r
322                 self.max_health = self.health;\r
323                 self.th_die = multi_killed;             // added by xavior\r
324                 self.event_damage = multi_eventdamage;\r
325                 self.takedamage = DAMAGE_YES;\r
326                 self.solid = SOLID_BBOX;\r
327                 setorigin (self, self.origin);  // make sure it links into the world\r
328         }\r
329         else\r
330         {\r
331                 if ( !(self.spawnflags & SPAWNFLAG_NOTOUCH) )\r
332                 {\r
333                         self.touch = multi_touch;\r
334                 }\r
335         }\r
336 };\r
337 \r
338 \r
339 /*QUAKED trigger_once (.5 .5 .5) ? notouch\r
340 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\r
341 "targetname".  If "health" is set, the trigger must be killed to activate.\r
342 If notouch is set, the trigger is only fired by other entities, not by touching.\r
343 if "killtarget" is set, any objects that have a matching "target" will be removed when the trigger is fired.\r
344 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.\r
345 sounds\r
346 1)      secret\r
347 2)      beep beep\r
348 3)      large switch\r
349 4)\r
350 set "message" to text string\r
351 */\r
352 /*void() trigger_once =\r
353 {\r
354         self.wait = -1;\r
355         trigger_multiple();\r
356 };*/\r
357 \r
358 //=============================================================================\r
359 \r
360 /*QUAKED trigger_relay (.5 .5 .5) (-8 -8 -8) (8 8 8)\r
361 This fixed size trigger cannot be touched, it can only be fired by other events.  It can contain killtargets, targets, delays, and messages.\r
362 */\r
363 void() trigger_relay =\r
364 {\r
365         self.use = SUB_UseTargets;\r
366 };\r
367 \r
368 \r
369 //=============================================================================\r
370 \r
371 \r
372 void() counter_use =\r
373 {\r
374         self.count = self.count - 1;\r
375         if (self.count < 0)\r
376                 return;\r
377 \r
378         if (self.count != 0)\r
379         {\r
380                 if (activator.classname == "player"\r
381                 && (self.spawnflags & SPAWNFLAG_NOMESSAGE) == 0)\r
382                 {\r
383                         if (self.count >= 4)\r
384                                 centerprint (activator, "There are more to go...");\r
385                         else if (self.count == 3)\r
386                                 centerprint (activator, "Only 3 more to go...");\r
387                         else if (self.count == 2)\r
388                                 centerprint (activator, "Only 2 more to go...");\r
389                         else\r
390                                 centerprint (activator, "Only 1 more to go...");\r
391                 }\r
392                 return;\r
393         }\r
394 \r
395         if (activator.classname == "player"\r
396         && (self.spawnflags & SPAWNFLAG_NOMESSAGE) == 0)\r
397                 centerprint(activator, "Sequence completed!");\r
398         self.enemy = activator;\r
399         multi_trigger ();\r
400 };\r
401 \r
402 /*QUAKED trigger_counter (.5 .5 .5) ? nomessage\r
403 Acts as an intermediary for an action that takes multiple inputs.\r
404 \r
405 If nomessage is not set, t will print "1 more.. " etc when triggered and "sequence complete" when finished.\r
406 \r
407 After the counter has been triggered "count" times (default 2), it will fire all of it's targets and remove itself.\r
408 */\r
409 void() trigger_counter =\r
410 {\r
411         self.wait = -1;\r
412         if (!self.count)\r
413                 self.count = 2;\r
414 \r
415         self.use = counter_use;\r
416 };\r
417 \r
418 /*.float triggerhurttime;\r
419 void() hurt_touch =\r
420 {\r
421         if (other.takedamage)\r
422         if (other.triggerhurttime < time)\r
423         {\r
424                 other.triggerhurttime = time + 1;\r
425                 Damage (other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');\r
426         }\r
427 \r
428         return;\r
429 };*/\r
430 \r
431 /*QUAKED trigger_hurt (.5 .5 .5) ?\r
432 Any object touching this will be hurt\r
433 set dmg to damage amount\r
434 defalt dmg = 5\r
435 */\r
436 /*void() trigger_hurt =\r
437 {\r
438         InitTrigger ();\r
439         self.touch = hurt_touch;\r
440         if (!self.dmg)\r
441                 self.dmg = 1000;\r
442         if (!self.message)\r
443                 self.message = "was in the wrong place.";\r
444 };*/\r
445 \r
446 //void() target_speaker_use = {sound(self, CHAN_VOICE, self.noise, 1, 1);}\r
447 //void() target_speaker = {self.use = target_speaker_use;}\r
448 \r
449 void() target_speaker =\r
450 {\r
451 if(self.noise) {\r
452  precache_sound (self.noise);\r
453  ambientsound (self.origin, self.noise, 1, ATTN_STATIC);\r
454 }\r
455 //remove(self);\r
456 };\r
457 \r
458 \r
459 /*\r
460 void() sparksthink =\r
461 {\r
462   self.nextthink = time + 0.1;\r
463 \r
464   if(random() < self.wait) {\r
465     te_spark(self.origin,'0 0 -1',self.cnt);\r
466   }\r
467 }\r
468 \r
469 \r
470 void() func_sparks =\r
471 {\r
472   self.think = sparksthink;\r
473   self.nextthink = time + 0.2;\r
474 \r
475   // self.cnt is the amount of sparks that one burst will spawn\r
476   if(self.cnt < 1) {\r
477     self.cnt = 25.0; // nice default value\r
478   }\r
479 \r
480   // self.wait is the probability that a sparkthink will spawn a spark shower\r
481   // range: 0 - 1, but 0 makes little sense, so...\r
482   if(self.wait < 0.05) {\r
483     self.wait = 0.25; // nice default value\r
484   }\r
485 \r
486   // sound\r
487   if(self.noise) {\r
488     precache_sound (self.noise);\r
489     ambientsound (self.origin, self.noise, 1, ATTN_STATIC);\r
490   }\r
491 }\r
492 */\r
493 \r
494 \r
495 /*\r
496 =============================================================================\r
497 \r
498 SECRET DOORS\r
499 \r
500 =============================================================================\r
501 */\r
502 // Doors are in TFDOORS.C\r
503 /*void() fd_secret_move1;\r
504 void() fd_secret_move2;\r
505 void() fd_secret_move3;\r
506 void() fd_secret_move4;\r
507 void() fd_secret_move5;\r
508 void() fd_secret_move6;\r
509 void() fd_secret_done;\r
510 \r
511 float SECRET_OPEN_ONCE = 1;             // stays open\r
512 float SECRET_1ST_LEFT = 2;              // 1st move is left of arrow\r
513 float SECRET_1ST_DOWN = 4;              // 1st move is down from arrow\r
514 float SECRET_NO_SHOOT = 8;              // only opened by trigger\r
515 float SECRET_YES_SHOOT = 16;    // shootable even if targeted\r
516 \r
517 \r
518 void () fd_secret_use =\r
519 {\r
520         local float temp;\r
521 \r
522         self.health = 10000;\r
523         //self.havocattack = TRUE;\r
524 \r
525         // exit if still moving around...\r
526         if (self.origin != self.oldorigin)\r
527                 return;\r
528 \r
529         self.message = ""; // no more message\r
530 \r
531         SUB_UseTargets();                               // fire all targets / killtargets\r
532 \r
533         self.velocity = '0 0 0';\r
534 \r
535         // Make a sound, wait a little...\r
536 \r
537         if (self.noise1 != "")\r
538                 sound(self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);\r
539         self.nextthink = self.ltime + 0.1;\r
540 \r
541         temp = 1 - (self.spawnflags & SECRET_1ST_LEFT); // 1 or -1\r
542         makevectors(self.mangle);\r
543 \r
544         if (!self.t_width)\r
545         {\r
546                 if (self.spawnflags & SECRET_1ST_DOWN)\r
547                         self.t_width = fabs(v_up * self.size);\r
548                 else\r
549                         self.t_width = fabs(v_right * self.size);\r
550         }\r
551 \r
552         if (!self.t_length)\r
553                 self.t_length = fabs(v_forward * self.size);\r
554 \r
555         if (self.spawnflags & SECRET_1ST_DOWN)\r
556                 self.dest1 = self.origin - v_up * self.t_width;\r
557         else\r
558                 self.dest1 = self.origin + v_right * (self.t_width * temp);\r
559 \r
560         self.dest2 = self.dest1 + v_forward * self.t_length;\r
561         SUB_CalcMove(self.dest1, self.speed, fd_secret_move1);\r
562         if (self.noise2 != "")\r
563                 sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);\r
564 };\r
565 \r
566 // Wait after first movement...\r
567 void () fd_secret_move1 =\r
568 {\r
569         self.nextthink = self.ltime + 1.0;\r
570         self.think = fd_secret_move2;\r
571         if (self.noise3 != "")\r
572                 sound(self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);\r
573 };\r
574 \r
575 // Start moving sideways w/sound...\r
576 void () fd_secret_move2 =\r
577 {\r
578         if (self.noise2 != "")\r
579                 sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);\r
580         SUB_CalcMove(self.dest2, self.speed, fd_secret_move3);\r
581 };\r
582 \r
583 // Wait here until time to go back...\r
584 void () fd_secret_move3 =\r
585 {\r
586         if (self.noise3 != "")\r
587                 sound(self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);\r
588         if (!(self.spawnflags & SECRET_OPEN_ONCE))\r
589         {\r
590                 self.nextthink = self.ltime + self.wait;\r
591                 self.think = fd_secret_move4;\r
592         }\r
593 };\r
594 \r
595 // Move backward...\r
596 void () fd_secret_move4 =\r
597 {\r
598         if (self.noise2 != "")\r
599                 sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);\r
600         SUB_CalcMove(self.dest1, self.speed, fd_secret_move5);\r
601 };\r
602 \r
603 // Wait 1 second...\r
604 void () fd_secret_move5 =\r
605 {\r
606         self.nextthink = self.ltime + 1.0;\r
607         self.think = fd_secret_move6;\r
608         if (self.noise3 != "")\r
609                 sound(self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);\r
610 };\r
611 \r
612 void () fd_secret_move6 =\r
613 {\r
614         if (self.noise2 != "")\r
615                 sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);\r
616         SUB_CalcMove(self.oldorigin, self.speed, fd_secret_done);\r
617 };\r
618 \r
619 void () fd_secret_done =\r
620 {\r
621         if (!self.targetname || self.spawnflags&SECRET_YES_SHOOT)\r
622         {\r
623                 self.health = 10000;\r
624                 self.takedamage = DAMAGE_YES;\r
625                 //self.th_pain = fd_secret_use;\r
626         }\r
627         if (self.noise3 != "")\r
628                 sound(self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);\r
629 };\r
630 \r
631 void () secret_blocked =\r
632 {\r
633         if (time < self.attack_finished)\r
634                 return;\r
635         self.attack_finished = time + 0.5;\r
636         //T_Damage (other, self, self, self.dmg, self.dmg, self.deathtype, DT_IMPACT, (self.absmin + self.absmax) * 0.5, '0 0 0', Obituary_Generic);\r
637 };*/\r
638 \r
639 /*\r
640 ==============\r
641 secret_touch\r
642 \r
643 Prints messages\r
644 ================\r
645 */ // now in TFDOORS.C\r
646 /*void() secret_touch =\r
647 {\r
648         if (activator.classname != "player")\r
649                 return;\r
650         if (self.attack_finished > time)\r
651                 return;\r
652 \r
653         self.attack_finished = time + 2;\r
654 \r
655         if (self.message)\r
656         {\r
657                 if (other.flags & FL_CLIENT)\r
658                         centerprint (other, self.message);\r
659                 sound (other, CHAN_BODY, "misc/talk.wav", 1, ATTN_NORM);\r
660         }\r
661 };*/\r
662 \r
663 \r
664 /*QUAKED func_door_secret (0 .5 .8) ? open_once 1st_left 1st_down no_shoot always_shoot\r
665 Basic secret door. Slides back, then to the side. Angle determines direction.\r
666 wait  = # of seconds before coming back\r
667 1st_left = 1st move is left of arrow\r
668 1st_down = 1st move is down from arrow\r
669 always_shoot = even if targeted, keep shootable\r
670 t_width = override WIDTH to move back (or height if going down)\r
671 t_length = override LENGTH to move sideways\r
672 "dmg"           damage to inflict when blocked (2 default)\r
673 \r
674 If a secret door has a targetname, it will only be opened by it's botton or trigger, not by damage.\r
675 "sounds"\r
676 1) medieval\r
677 2) metal\r
678 3) base\r
679 */\r
680 \r
681 /*void () func_door_secret =\r
682 {\r
683         /*if (!self.deathtype) // map makers can override this\r
684                 self.deathtype = " got in the way";*/\r
685 /*\r
686         if (!self.dmg)\r
687                 self.dmg = 2;\r
688 \r
689         // Magic formula...\r
690         self.mangle = self.angles;\r
691         self.angles = '0 0 0';\r
692         self.solid = SOLID_BSP;\r
693         self.movetype = MOVETYPE_PUSH;\r
694         self.classname = "door";\r
695         setmodel (self, self.model);\r
696         setorigin (self, self.origin);\r
697 \r
698         self.touch = secret_touch;\r
699         self.blocked = secret_blocked;\r
700         self.speed = 50;\r
701         self.use = fd_secret_use;\r
702         if ( !self.targetname || self.spawnflags&SECRET_YES_SHOOT)\r
703         {\r
704                 self.health = 10000;\r
705                 self.takedamage = DAMAGE_YES;\r
706                 self.event_damage = fd_secret_use;\r
707         }\r
708         self.oldorigin = self.origin;\r
709         if (!self.wait)\r
710                 self.wait = 5;          // 5 seconds before closing\r
711 };*/\r
712 \r
713 \r
714 // TF DOORS                     // MOVED THIS TO SEPERATE TF DOORS FILE\r
715 \r
716 // MOVE TO TFTRIGGERS\r
717 void() trigger_once = \r
718 {\r
719         if (CheckExistence() == TF_FLARE_LIT)\r
720         {\r
721                 dremove(self);\r
722                 return;\r
723         }\r
724         self.wait = -1;\r
725         trigger_multiple();\r
726 };\r
727 \r
728 void() hurt_on = \r
729 {\r
730         self.solid = TF_FLARE_OFF;\r
731         self.nextthink = -1;\r
732 };\r
733 \r
734 void() hurt_touch = \r
735 {\r
736         local entity te;\r
737         if (other.is_dead != 0)         // added by xavior to stop killing of dead bodies\r
738                 return;                                         ////\r
739         if (other.takedamage)\r
740         {\r
741                 if (!Activated(self, other))\r
742                 {\r
743                         if (self.else_goal != TF_FLARE_LIT)\r
744                         {\r
745                                 te = Findgoal(self.else_goal);\r
746                                 if (te)\r
747                                 {\r
748                                         DoResults(te, other, self.goal_result & 2);\r
749                                 }\r
750                         }\r
751                         return;\r
752                 }\r
753                 self.solid = TF_FLARE_LIT;\r
754                 deathmsg = 36;\r
755                 TF_T_Damage(other, self, self, self.dmg, TF_FLARE_OFF, TF_FLARE_LIT);\r
756                 self.think = hurt_on;\r
757                 self.nextthink = time + TF_FLARE_OFF;\r
758         }\r
759 };\r
760 \r
761 void() trigger_hurt = \r
762 {\r
763         if (self.allowteams == "red")           // Converted to work with q3f/ETF entities\r
764         {\r
765                 self.team_no = 2;\r
766                 self.owned_by = 2;\r
767         }\r
768         if (self.allowteams == "blue")\r
769         {\r
770                 self.owned_by = 1;\r
771                 self.team_no = 1;\r
772         }\r
773 \r
774         if (CheckExistence() == TF_FLARE_LIT)\r
775         {\r
776                 dremove(self);\r
777                 return;\r
778         }\r
779         InitTrigger();\r
780         self.touch = hurt_touch;\r
781         if (!(self.dmg))\r
782         {\r
783                 self.dmg = 5;\r
784         }\r
785 };\r
786 \r
787 \r
788 // TF SUBS\r
789 void () SUB_UseTargets =\r
790 {\r
791         local entity t;\r
792         local entity stemp;\r
793         local entity otemp;\r
794         local entity act;\r
795 \r
796         if (self.dont_do_triggerwork)\r
797         {\r
798                 self.dont_do_triggerwork = 0;\r
799                 return;\r
800         }\r
801         if (self.delay)\r
802         {\r
803                 t = spawn ();\r
804                 t.classname = "DelayedUse";\r
805                 t.nextthink = (time + self.delay);\r
806                 t.think = DelayThink;\r
807                 t.enemy = activator;\r
808                 t.message = self.message;\r
809                 t.killtarget = self.killtarget;\r
810                 t.target = self.target;\r
811                 return;\r
812         }\r
813         if (((activator.classname == "player") && (self.message != "")))\r
814         {\r
815                 CenterPrint (activator, self.message);\r
816                 if (!self.noise)\r
817                 {\r
818                         sound (activator, 2, "misc/talk.wav", 1, 1);\r
819                 }\r
820         }\r
821         if ((activator.classname == "player"))\r
822         {\r
823                 DoGroupWork (self, activator);\r
824                 DoGoalWork (self, activator);\r
825         }\r
826         if (self.killtarget)\r
827         {\r
828                 t = world;\r
829                 do\r
830                 {\r
831                         t = find (t, targetname, self.killtarget);\r
832                         if (!t)\r
833                         {\r
834                                 return;\r
835                         }\r
836                         remove (t);\r
837 \r
838                 } while (1);\r
839         }\r
840         if (self.target)\r
841         {\r
842                 act = activator;\r
843                 t = world;\r
844                 do\r
845                 {\r
846                         t = find (t, targetname, self.target);\r
847                         if (!t)\r
848                         {\r
849                                 return;\r
850                         }\r
851                         stemp = self;\r
852                         otemp = other;\r
853                         self = t;\r
854                         other = stemp;\r
855                         if ((self.use != SUB_Null))\r
856                         {\r
857                                 if (self.use)\r
858                                 {\r
859                                         self.use ();\r
860                                 }\r
861                         }\r
862                         self = stemp;\r
863                         other = otemp;\r
864                         activator = act;\r
865 \r
866                 } while (1);\r
867         }\r
868 };\r
869 \r