doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Trigger.cpp
Go to the documentation of this file.
1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 #include "../idlib/precompiled.h"
30 #pragma hdrstop
31 
32 #include "Game_local.h"
33 
34 
35 /*
36 ===============================================================================
37 
38  idTrigger
39 
40 ===============================================================================
41 */
42 
43 const idEventDef EV_Enable( "enable", NULL );
44 const idEventDef EV_Disable( "disable", NULL );
45 
47  EVENT( EV_Enable, idTrigger::Event_Enable )
48  EVENT( EV_Disable, idTrigger::Event_Disable )
50 
51 /*
52 ================
53 idTrigger::DrawDebugInfo
54 ================
55 */
56 void idTrigger::DrawDebugInfo( void ) {
58  idVec3 up = axis[ 2 ] * 5.0f;
59  idBounds viewTextBounds( gameLocal.GetLocalPlayer()->GetPhysics()->GetOrigin() );
61  idBounds box( idVec3( -4.0f, -4.0f, -4.0f ), idVec3( 4.0f, 4.0f, 4.0f ) );
62  idEntity *ent;
63  idEntity *target;
64  int i;
65  bool show;
66  const function_t *func;
67 
68  viewTextBounds.ExpandSelf( 128.0f );
69  viewBounds.ExpandSelf( 512.0f );
70  for( ent = gameLocal.spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() ) {
72  show = viewBounds.IntersectsBounds( ent->GetPhysics()->GetAbsBounds() );
73  if ( !show ) {
74  for( i = 0; i < ent->targets.Num(); i++ ) {
75  target = ent->targets[ i ].GetEntity();
76  if ( target && viewBounds.IntersectsBounds( target->GetPhysics()->GetAbsBounds() ) ) {
77  show = true;
78  break;
79  }
80  }
81  }
82 
83  if ( !show ) {
84  continue;
85  }
86 
88  if ( viewTextBounds.IntersectsBounds( ent->GetPhysics()->GetAbsBounds() ) ) {
89  gameRenderWorld->DrawText( ent->name.c_str(), ent->GetPhysics()->GetAbsBounds().GetCenter(), 0.1f, colorWhite, axis, 1 );
90  gameRenderWorld->DrawText( ent->GetEntityDefName(), ent->GetPhysics()->GetAbsBounds().GetCenter() + up, 0.1f, colorWhite, axis, 1 );
91  if ( ent->IsType( idTrigger::Type ) ) {
92  func = static_cast<idTrigger *>( ent )->GetScriptFunction();
93  } else {
94  func = NULL;
95  }
96 
97  if ( func ) {
98  gameRenderWorld->DrawText( va( "call script '%s'", func->Name() ), ent->GetPhysics()->GetAbsBounds().GetCenter() - up, 0.1f, colorWhite, axis, 1 );
99  }
100  }
101 
102  for( i = 0; i < ent->targets.Num(); i++ ) {
103  target = ent->targets[ i ].GetEntity();
104  if ( target ) {
107  if ( viewTextBounds.IntersectsBounds( target->GetPhysics()->GetAbsBounds() ) ) {
108  gameRenderWorld->DrawText( target->name.c_str(), target->GetPhysics()->GetAbsBounds().GetCenter(), 0.1f, colorWhite, axis, 1 );
109  }
110  }
111  }
112  }
113  }
114 }
115 
116 /*
117 ================
118 idTrigger::Enable
119 ================
120 */
121 void idTrigger::Enable( void ) {
123  GetPhysics()->EnableClip();
124 }
125 
126 /*
127 ================
128 idTrigger::Disable
129 ================
130 */
131 void idTrigger::Disable( void ) {
132  // we may be relinked if we're bound to another object, so clear the contents as well
133  GetPhysics()->SetContents( 0 );
134  GetPhysics()->DisableClip();
135 }
136 
137 /*
138 ================
139 idTrigger::CallScript
140 ================
141 */
142 void idTrigger::CallScript( void ) const {
143  idThread *thread;
144 
145  if ( scriptFunction ) {
146  thread = new idThread( scriptFunction );
147  thread->DelayedStart( 0 );
148  }
149 }
150 
151 /*
152 ================
153 idTrigger::GetScriptFunction
154 ================
155 */
157  return scriptFunction;
158 }
159 
160 /*
161 ================
162 idTrigger::Save
163 ================
164 */
165 void idTrigger::Save( idSaveGame *savefile ) const {
166  if ( scriptFunction ) {
167  savefile->WriteString( scriptFunction->Name() );
168  } else {
169  savefile->WriteString( "" );
170  }
171 }
172 
173 /*
174 ================
175 idTrigger::Restore
176 ================
177 */
179  idStr funcname;
180  savefile->ReadString( funcname );
181  if ( funcname.Length() ) {
183  if ( scriptFunction == NULL ) {
184  gameLocal.Warning( "idTrigger_Multi '%s' at (%s) calls unknown function '%s'", name.c_str(), GetPhysics()->GetOrigin().ToString(0), funcname.c_str() );
185  }
186  } else {
188  }
189 }
190 
191 /*
192 ================
193 idTrigger::Event_Enable
194 ================
195 */
197  Enable();
198 }
199 
200 /*
201 ================
202 idTrigger::Event_Disable
203 ================
204 */
206  Disable();
207 }
208 
209 /*
210 ================
211 idTrigger::idTrigger
212 ================
213 */
216 }
217 
218 /*
219 ================
220 idTrigger::Spawn
221 ================
222 */
223 void idTrigger::Spawn( void ) {
225 
226  idStr funcname = spawnArgs.GetString( "call", "" );
227  if ( funcname.Length() ) {
229  if ( scriptFunction == NULL ) {
230  gameLocal.Warning( "trigger '%s' at (%s) calls unknown function '%s'", name.c_str(), GetPhysics()->GetOrigin().ToString(0), funcname.c_str() );
231  }
232  } else {
234  }
235 }
236 
237 
238 /*
239 ===============================================================================
240 
241  idTrigger_Multi
242 
243 ===============================================================================
244 */
245 
246 const idEventDef EV_TriggerAction( "<triggerAction>", "e" );
247 
249  EVENT( EV_Touch, idTrigger_Multi::Event_Touch )
250  EVENT( EV_Activate, idTrigger_Multi::Event_Trigger )
251  EVENT( EV_TriggerAction, idTrigger_Multi::Event_TriggerAction )
252 END_CLASS
253 
254 
255 /*
256 ================
257 idTrigger_Multi::idTrigger_Multi
258 ================
259 */
261  wait = 0.0f;
262  random = 0.0f;
263  delay = 0.0f;
264  random_delay = 0.0f;
265  nextTriggerTime = 0;
266  removeItem = 0;
267  touchClient = false;
268  touchOther = false;
269  triggerFirst = false;
270  triggerWithSelf = false;
271 }
272 
273 /*
274 ================
275 idTrigger_Multi::Save
276 ================
277 */
278 void idTrigger_Multi::Save( idSaveGame *savefile ) const {
279  savefile->WriteFloat( wait );
280  savefile->WriteFloat( random );
281  savefile->WriteFloat( delay );
282  savefile->WriteFloat( random_delay );
283  savefile->WriteInt( nextTriggerTime );
284  savefile->WriteString( requires );
285  savefile->WriteInt( removeItem );
286  savefile->WriteBool( touchClient );
287  savefile->WriteBool( touchOther );
288  savefile->WriteBool( triggerFirst );
289  savefile->WriteBool( triggerWithSelf );
290 }
291 
292 /*
293 ================
294 idTrigger_Multi::Restore
295 ================
296 */
298  savefile->ReadFloat( wait );
299  savefile->ReadFloat( random );
300  savefile->ReadFloat( delay );
301  savefile->ReadFloat( random_delay );
302  savefile->ReadInt( nextTriggerTime );
303  savefile->ReadString( requires );
304  savefile->ReadInt( removeItem );
305  savefile->ReadBool( touchClient );
306  savefile->ReadBool( touchOther );
307  savefile->ReadBool( triggerFirst );
308  savefile->ReadBool( triggerWithSelf );
309 }
310 
311 /*
312 ================
313 idTrigger_Multi::Spawn
314 
315 "wait" : Seconds between triggerings, 0.5 default, -1 = one time only.
316 "call" : Script function to call when triggered
317 "random" wait variance, default is 0
318 Variable sized repeatable trigger. Must be targeted at one or more entities.
319 so, the basic time between firing is a random time between
320 (wait - random) and (wait + random)
321 ================
322 */
324  spawnArgs.GetFloat( "wait", "0.5", wait );
325  spawnArgs.GetFloat( "random", "0", random );
326  spawnArgs.GetFloat( "delay", "0", delay );
327  spawnArgs.GetFloat( "random_delay", "0", random_delay );
328 
329  if ( random && ( random >= wait ) && ( wait >= 0 ) ) {
330  random = wait - 1;
331  gameLocal.Warning( "idTrigger_Multi '%s' at (%s) has random >= wait", name.c_str(), GetPhysics()->GetOrigin().ToString(0) );
332  }
333 
334  if ( random_delay && ( random_delay >= delay ) && ( delay >= 0 ) ) {
335  random_delay = delay - 1;
336  gameLocal.Warning( "idTrigger_Multi '%s' at (%s) has random_delay >= delay", name.c_str(), GetPhysics()->GetOrigin().ToString(0) );
337  }
338 
339  spawnArgs.GetString( "requires", "", requires );
340  spawnArgs.GetInt( "removeItem", "0", removeItem );
341  spawnArgs.GetBool( "triggerFirst", "0", triggerFirst );
342  spawnArgs.GetBool( "triggerWithSelf", "0", triggerWithSelf );
343 
344  if ( spawnArgs.GetBool( "anyTouch" ) ) {
345  touchClient = true;
346  touchOther = true;
347  } else if ( spawnArgs.GetBool( "noTouch" ) ) {
348  touchClient = false;
349  touchOther = false;
350  } else if ( spawnArgs.GetBool( "noClient" ) ) {
351  touchClient = false;
352  touchOther = true;
353  } else {
354  touchClient = true;
355  touchOther = false;
356  }
357 
358  nextTriggerTime = 0;
359 
360  if ( spawnArgs.GetBool( "flashlight_trigger" ) ) {
362  } else {
364  }
365 }
366 
367 /*
368 ================
369 idTrigger_Multi::CheckFacing
370 ================
371 */
373  if ( spawnArgs.GetBool( "facing" ) ) {
374  if ( !activator->IsType( idPlayer::Type ) ) {
375  return true;
376  }
377  idPlayer *player = static_cast< idPlayer* >( activator );
378  float dot = player->viewAngles.ToForward() * GetPhysics()->GetAxis()[0];
379  float angle = RAD2DEG( idMath::ACos( dot ) );
380  if ( angle > spawnArgs.GetFloat( "angleLimit", "30" ) ) {
381  return false;
382  }
383  }
384  return true;
385 }
386 
387 
388 /*
389 ================
390 idTrigger_Multi::TriggerAction
391 ================
392 */
394  ActivateTargets( triggerWithSelf ? this : activator );
395  CallScript();
396 
397  if ( wait >= 0 ) {
399  } else {
400  // we can't just remove (this) here, because this is a touch function
401  // called while looping through area links...
402 #ifdef _D3XP
403  // If the player spawned inside the trigger, the player Spawn function called Think directly,
404  // allowing for multiple triggers on a trigger_once. Increasing the nextTriggerTime prevents it.
405  nextTriggerTime = gameLocal.time + 99999;
406 #else
408 #endif
409  PostEventMS( &EV_Remove, 0 );
410  }
411 }
412 
413 /*
414 ================
415 idTrigger_Multi::Event_TriggerAction
416 ================
417 */
419  TriggerAction( activator );
420 }
421 
422 /*
423 ================
424 idTrigger_Multi::Event_Trigger
425 
426 the trigger was just activated
427 activated should be the entity that originated the activation sequence (ie. the original target)
428 activator should be set to the activator so it can be held through a delay
429 so wait for the delay time before firing
430 ================
431 */
433  if ( nextTriggerTime > gameLocal.time ) {
434  // can't retrigger until the wait is over
435  return;
436  }
437 
438  // see if this trigger requires an item
439  if ( !gameLocal.RequirementMet( activator, requires, removeItem ) ) {
440  return;
441  }
442 
443  if ( !CheckFacing( activator ) ) {
444  return;
445  }
446 
447  if ( triggerFirst ) {
448  triggerFirst = false;
449  return;
450  }
451 
452  // don't allow it to trigger twice in a single frame
454 
455  if ( delay > 0 ) {
456  // don't allow it to trigger again until our delay has passed
458  PostEventSec( &EV_TriggerAction, delay, activator );
459  } else {
460  TriggerAction( activator );
461  }
462 }
463 
464 /*
465 ================
466 idTrigger_Multi::Event_Touch
467 ================
468 */
470  if( triggerFirst ) {
471  return;
472  }
473 
474  bool player = other->IsType( idPlayer::Type );
475  if ( player ) {
476  if ( !touchClient ) {
477  return;
478  }
479  if ( static_cast< idPlayer * >( other )->spectating ) {
480  return;
481  }
482  } else if ( !touchOther ) {
483  return;
484  }
485 
486  if ( nextTriggerTime > gameLocal.time ) {
487  // can't retrigger until the wait is over
488  return;
489  }
490 
491  // see if this trigger requires an item
492  if ( !gameLocal.RequirementMet( other, requires, removeItem ) ) {
493  return;
494  }
495 
496  if ( !CheckFacing( other ) ) {
497  return;
498  }
499 
500  if ( spawnArgs.GetBool( "toggleTriggerFirst" ) ) {
501  triggerFirst = true;
502  }
503 
505  if ( delay > 0 ) {
506  // don't allow it to trigger again until our delay has passed
508  PostEventSec( &EV_TriggerAction, delay, other );
509  } else {
510  TriggerAction( other );
511  }
512 }
513 
514 /*
515 ===============================================================================
516 
517  idTrigger_EntityName
518 
519 ===============================================================================
520 */
521 
523  EVENT( EV_Touch, idTrigger_EntityName::Event_Touch )
524  EVENT( EV_Activate, idTrigger_EntityName::Event_Trigger )
525  EVENT( EV_TriggerAction, idTrigger_EntityName::Event_TriggerAction )
526 END_CLASS
527 
528 /*
529 ================
530 idTrigger_EntityName::idTrigger_EntityName
531 ================
532 */
534  wait = 0.0f;
535  random = 0.0f;
536  delay = 0.0f;
537  random_delay = 0.0f;
538  nextTriggerTime = 0;
539  triggerFirst = false;
540 }
541 
542 /*
543 ================
544 idTrigger_EntityName::Save
545 ================
546 */
547 void idTrigger_EntityName::Save( idSaveGame *savefile ) const {
548  savefile->WriteFloat( wait );
549  savefile->WriteFloat( random );
550  savefile->WriteFloat( delay );
551  savefile->WriteFloat( random_delay );
552  savefile->WriteInt( nextTriggerTime );
553  savefile->WriteBool( triggerFirst );
554  savefile->WriteString( entityName );
555 }
556 
557 /*
558 ================
559 idTrigger_EntityName::Restore
560 ================
561 */
563  savefile->ReadFloat( wait );
564  savefile->ReadFloat( random );
565  savefile->ReadFloat( delay );
566  savefile->ReadFloat( random_delay );
567  savefile->ReadInt( nextTriggerTime );
568  savefile->ReadBool( triggerFirst );
569  savefile->ReadString( entityName );
570 }
571 
572 /*
573 ================
574 idTrigger_EntityName::Spawn
575 ================
576 */
578  spawnArgs.GetFloat( "wait", "0.5", wait );
579  spawnArgs.GetFloat( "random", "0", random );
580  spawnArgs.GetFloat( "delay", "0", delay );
581  spawnArgs.GetFloat( "random_delay", "0", random_delay );
582 
583  if ( random && ( random >= wait ) && ( wait >= 0 ) ) {
584  random = wait - 1;
585  gameLocal.Warning( "idTrigger_EntityName '%s' at (%s) has random >= wait", name.c_str(), GetPhysics()->GetOrigin().ToString(0) );
586  }
587 
588  if ( random_delay && ( random_delay >= delay ) && ( delay >= 0 ) ) {
589  random_delay = delay - 1;
590  gameLocal.Warning( "idTrigger_EntityName '%s' at (%s) has random_delay >= delay", name.c_str(), GetPhysics()->GetOrigin().ToString(0) );
591  }
592 
593  spawnArgs.GetBool( "triggerFirst", "0", triggerFirst );
594 
595  entityName = spawnArgs.GetString( "entityname" );
596  if ( !entityName.Length() ) {
597  gameLocal.Error( "idTrigger_EntityName '%s' at (%s) doesn't have 'entityname' key specified", name.c_str(), GetPhysics()->GetOrigin().ToString(0) );
598  }
599 
600  nextTriggerTime = 0;
601 
602  if ( !spawnArgs.GetBool( "noTouch" ) ) {
604  }
605 }
606 
607 /*
608 ================
609 idTrigger_EntityName::TriggerAction
610 ================
611 */
613  ActivateTargets( activator );
614  CallScript();
615 
616  if ( wait >= 0 ) {
618  } else {
619  // we can't just remove (this) here, because this is a touch function
620  // called while looping through area links...
622  PostEventMS( &EV_Remove, 0 );
623  }
624 }
625 
626 /*
627 ================
628 idTrigger_EntityName::Event_TriggerAction
629 ================
630 */
632  TriggerAction( activator );
633 }
634 
635 /*
636 ================
637 idTrigger_EntityName::Event_Trigger
638 
639 the trigger was just activated
640 activated should be the entity that originated the activation sequence (ie. the original target)
641 activator should be set to the activator so it can be held through a delay
642 so wait for the delay time before firing
643 ================
644 */
646  if ( nextTriggerTime > gameLocal.time ) {
647  // can't retrigger until the wait is over
648  return;
649  }
650 
651  if ( !activator || ( activator->name != entityName ) ) {
652  return;
653  }
654 
655  if ( triggerFirst ) {
656  triggerFirst = false;
657  return;
658  }
659 
660  // don't allow it to trigger twice in a single frame
662 
663  if ( delay > 0 ) {
664  // don't allow it to trigger again until our delay has passed
666  PostEventSec( &EV_TriggerAction, delay, activator );
667  } else {
668  TriggerAction( activator );
669  }
670 }
671 
672 /*
673 ================
674 idTrigger_EntityName::Event_Touch
675 ================
676 */
678  if( triggerFirst ) {
679  return;
680  }
681 
682  if ( nextTriggerTime > gameLocal.time ) {
683  // can't retrigger until the wait is over
684  return;
685  }
686 
687  if ( !other || ( other->name != entityName ) ) {
688  return;
689  }
690 
692  if ( delay > 0 ) {
693  // don't allow it to trigger again until our delay has passed
695  PostEventSec( &EV_TriggerAction, delay, other );
696  } else {
697  TriggerAction( other );
698  }
699 }
700 
701 /*
702 ===============================================================================
703 
704  idTrigger_Timer
705 
706 ===============================================================================
707 */
708 
709 const idEventDef EV_Timer( "<timer>", NULL );
710 
712  EVENT( EV_Timer, idTrigger_Timer::Event_Timer )
713  EVENT( EV_Activate, idTrigger_Timer::Event_Use )
714 END_CLASS
715 
716 /*
717 ================
718 idTrigger_Timer::idTrigger_Timer
719 ================
720 */
722  random = 0.0f;
723  wait = 0.0f;
724  on = false;
725  delay = 0.0f;
726 }
727 
728 /*
729 ================
730 idTrigger_Timer::Save
731 ================
732 */
733 void idTrigger_Timer::Save( idSaveGame *savefile ) const {
734  savefile->WriteFloat( random );
735  savefile->WriteFloat( wait );
736  savefile->WriteBool( on );
737  savefile->WriteFloat( delay );
738  savefile->WriteString( onName );
739  savefile->WriteString( offName );
740 }
741 
742 /*
743 ================
744 idTrigger_Timer::Restore
745 ================
746 */
748  savefile->ReadFloat( random );
749  savefile->ReadFloat( wait );
750  savefile->ReadBool( on );
751  savefile->ReadFloat( delay );
752  savefile->ReadString( onName );
753  savefile->ReadString( offName );
754 }
755 
756 /*
757 ================
758 idTrigger_Timer::Spawn
759 
760 Repeatedly fires its targets.
761 Can be turned on or off by using.
762 ================
763 */
765  spawnArgs.GetFloat( "random", "1", random );
766  spawnArgs.GetFloat( "wait", "1", wait );
767  spawnArgs.GetBool( "start_on", "0", on );
768  spawnArgs.GetFloat( "delay", "0", delay );
769  onName = spawnArgs.GetString( "onName" );
770  offName = spawnArgs.GetString( "offName" );
771 
772  if ( random >= wait && wait >= 0 ) {
773  random = wait - 0.001;
774  gameLocal.Warning( "idTrigger_Timer '%s' at (%s) has random >= wait", name.c_str(), GetPhysics()->GetOrigin().ToString(0) );
775  }
776 
777  if ( on ) {
779  }
780 }
781 
782 /*
783 ================
784 idTrigger_Timer::Enable
785 ================
786 */
788  // if off, turn it on
789  if ( !on ) {
790  on = true;
792  }
793 }
794 
795 /*
796 ================
797 idTrigger_Timer::Disable
798 ================
799 */
801  // if on, turn it off
802  if ( on ) {
803  on = false;
805  }
806 }
807 
808 /*
809 ================
810 idTrigger_Timer::Event_Timer
811 ================
812 */
814  ActivateTargets( this );
815 
816  // set time before next firing
817  if ( wait >= 0.0f ) {
819  }
820 }
821 
822 /*
823 ================
824 idTrigger_Timer::Event_Use
825 ================
826 */
828  // if on, turn it off
829  if ( on ) {
830  if ( offName.Length() && offName.Icmp( activator->GetName() ) ) {
831  return;
832  }
833  on = false;
835  } else {
836  // turn it on
837  if ( onName.Length() && onName.Icmp( activator->GetName() ) ) {
838  return;
839  }
840  on = true;
842  }
843 }
844 
845 /*
846 ===============================================================================
847 
848  idTrigger_Count
849 
850 ===============================================================================
851 */
852 
854  EVENT( EV_Activate, idTrigger_Count::Event_Trigger )
855  EVENT( EV_TriggerAction, idTrigger_Count::Event_TriggerAction )
856 END_CLASS
857 
858 /*
859 ================
860 idTrigger_Count::idTrigger_Count
861 ================
862 */
864  goal = 0;
865  count = 0;
866  delay = 0.0f;
867 }
868 
869 /*
870 ================
871 idTrigger_Count::Save
872 ================
873 */
874 void idTrigger_Count::Save( idSaveGame *savefile ) const {
875  savefile->WriteInt( goal );
876  savefile->WriteInt( count );
877  savefile->WriteFloat( delay );
878 }
879 
880 /*
881 ================
882 idTrigger_Count::Restore
883 ================
884 */
886  savefile->ReadInt( goal );
887  savefile->ReadInt( count );
888  savefile->ReadFloat( delay );
889 }
890 
891 /*
892 ================
893 idTrigger_Count::Spawn
894 ================
895 */
897  spawnArgs.GetInt( "count", "1", goal );
898  spawnArgs.GetFloat( "delay", "0", delay );
899  count = 0;
900 }
901 
902 /*
903 ================
904 idTrigger_Count::Event_Trigger
905 ================
906 */
908  // goal of -1 means trigger has been exhausted
909  if (goal >= 0) {
910  count++;
911  if ( count >= goal ) {
912  if (spawnArgs.GetBool("repeat")) {
913  count = 0;
914  } else {
915  goal = -1;
916  }
917  PostEventSec( &EV_TriggerAction, delay, activator );
918  }
919  }
920 }
921 
922 /*
923 ================
924 idTrigger_Count::Event_TriggerAction
925 ================
926 */
928  ActivateTargets( activator );
929  CallScript();
930  if ( goal == -1 ) {
931  PostEventMS( &EV_Remove, 0 );
932  }
933 }
934 
935 /*
936 ===============================================================================
937 
938  idTrigger_Hurt
939 
940 ===============================================================================
941 */
942 
944  EVENT( EV_Touch, idTrigger_Hurt::Event_Touch )
945  EVENT( EV_Activate, idTrigger_Hurt::Event_Toggle )
946 END_CLASS
947 
948 
949 /*
950 ================
951 idTrigger_Hurt::idTrigger_Hurt
952 ================
953 */
955  on = false;
956  delay = 0.0f;
957  nextTime = 0;
958 }
959 
960 /*
961 ================
962 idTrigger_Hurt::Save
963 ================
964 */
965 void idTrigger_Hurt::Save( idSaveGame *savefile ) const {
966  savefile->WriteBool( on );
967  savefile->WriteFloat( delay );
968  savefile->WriteInt( nextTime );
969 }
970 
971 /*
972 ================
973 idTrigger_Hurt::Restore
974 ================
975 */
977  savefile->ReadBool( on );
978  savefile->ReadFloat( delay );
979  savefile->ReadInt( nextTime );
980 }
981 
982 /*
983 ================
984 idTrigger_Hurt::Spawn
985 
986  Damages activator
987  Can be turned on or off by using.
988 ================
989 */
990 void idTrigger_Hurt::Spawn( void ) {
991  spawnArgs.GetBool( "on", "1", on );
992  spawnArgs.GetFloat( "delay", "1.0", delay );
994  Enable();
995 }
996 
997 /*
998 ================
999 idTrigger_Hurt::Event_Touch
1000 ================
1001 */
1003  const char *damage;
1004 
1005  if ( on && other && gameLocal.time >= nextTime ) {
1006 #ifdef _D3XP
1007  bool playerOnly = spawnArgs.GetBool( "playerOnly" );
1008  if ( playerOnly ) {
1009  if ( !other->IsType( idPlayer::Type ) ) {
1010  return;
1011  }
1012  }
1013 #endif
1014  damage = spawnArgs.GetString( "def_damage", "damage_painTrigger" );
1015 
1016 #ifdef _D3XP
1017  idVec3 dir = vec3_origin;
1018  if(spawnArgs.GetBool("kick_from_center", "0")) {
1019  dir = other->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin();
1020  dir.Normalize();
1021  }
1022  other->Damage( NULL, NULL, dir, damage, 1.0f, INVALID_JOINT );
1023 #else
1024  other->Damage( NULL, NULL, vec3_origin, damage, 1.0f, INVALID_JOINT );
1025 #endif
1026 
1027  ActivateTargets( other );
1028  CallScript();
1029 
1031  }
1032 }
1033 
1034 /*
1035 ================
1036 idTrigger_Hurt::Event_Toggle
1037 ================
1038 */
1040  on = !on;
1041 }
1042 
1043 
1044 /*
1045 ===============================================================================
1046 
1047  idTrigger_Fade
1048 
1049 ===============================================================================
1050 */
1051 
1053  EVENT( EV_Activate, idTrigger_Fade::Event_Trigger )
1054 END_CLASS
1055 
1056 /*
1057 ================
1058 idTrigger_Fade::Event_Trigger
1059 ================
1060 */
1061 void idTrigger_Fade::Event_Trigger( idEntity *activator ) {
1062  idVec4 fadeColor;
1063  int fadeTime;
1064  idPlayer *player;
1065 
1066  player = gameLocal.GetLocalPlayer();
1067  if ( player ) {
1068  fadeColor = spawnArgs.GetVec4( "fadeColor", "0, 0, 0, 1" );
1069  fadeTime = SEC2MS( spawnArgs.GetFloat( "fadeTime", "0.5" ) );
1070  player->playerView.Fade( fadeColor, fadeTime );
1071  PostEventMS( &EV_ActivateTargets, fadeTime, activator );
1072  }
1073 }
1074 
1075 /*
1076 ===============================================================================
1077 
1078  idTrigger_Touch
1079 
1080 ===============================================================================
1081 */
1082 
1084  EVENT( EV_Activate, idTrigger_Touch::Event_Trigger )
1085 END_CLASS
1086 
1087 
1088 /*
1089 ================
1090 idTrigger_Touch::idTrigger_Touch
1091 ================
1092 */
1094  clipModel = NULL;
1095 }
1096 
1097 /*
1098 ================
1099 idTrigger_Touch::Spawn
1100 ================
1101 */
1103  // get the clip model
1104  clipModel = new idClipModel( GetPhysics()->GetClipModel() );
1105 
1106  // remove the collision model from the physics object
1107  GetPhysics()->SetClipModel( NULL, 1.0f );
1108 
1109  if ( spawnArgs.GetBool( "start_on" ) ) {
1111  }
1112 }
1113 
1114 /*
1115 ================
1116 idTrigger_Touch::Save
1117 ================
1118 */
1120  savefile->WriteClipModel( clipModel );
1121 }
1122 
1123 /*
1124 ================
1125 idTrigger_Touch::Restore
1126 ================
1127 */
1129  savefile->ReadClipModel( clipModel );
1130 }
1131 
1132 /*
1133 ================
1134 idTrigger_Touch::TouchEntities
1135 ================
1136 */
1138  int numClipModels, i;
1139  idBounds bounds;
1140  idClipModel *cm, *clipModelList[ MAX_GENTITIES ];
1141 
1142  if ( clipModel == NULL || scriptFunction == NULL ) {
1143  return;
1144  }
1145 
1147  numClipModels = gameLocal.clip.ClipModelsTouchingBounds( bounds, -1, clipModelList, MAX_GENTITIES );
1148 
1149  for ( i = 0; i < numClipModels; i++ ) {
1150  cm = clipModelList[ i ];
1151 
1152  if ( !cm->IsTraceModel() ) {
1153  continue;
1154  }
1155 
1156  idEntity *entity = cm->GetEntity();
1157 
1158  if ( !entity ) {
1159  continue;
1160  }
1161 
1162  if ( !gameLocal.clip.ContentsModel( cm->GetOrigin(), cm, cm->GetAxis(), -1,
1164  continue;
1165  }
1166 
1167  ActivateTargets( entity );
1168 
1169  idThread *thread = new idThread();
1170  thread->CallFunction( entity, scriptFunction, false );
1171  thread->DelayedStart( 0 );
1172  }
1173 }
1174 
1175 /*
1176 ================
1177 idTrigger_Touch::Think
1178 ================
1179 */
1181  if ( thinkFlags & TH_THINK ) {
1182  TouchEntities();
1183  }
1184  idEntity::Think();
1185 }
1186 
1187 /*
1188 ================
1189 idTrigger_Touch::Event_Trigger
1190 ================
1191 */
1193  if ( thinkFlags & TH_THINK ) {
1194  BecomeInactive( TH_THINK );
1195  } else {
1196  BecomeActive( TH_THINK );
1197  }
1198 }
1199 
1200 /*
1201 ================
1202 idTrigger_Touch::Enable
1203 ================
1204 */
1207 }
1208 
1209 /*
1210 ================
1211 idTrigger_Touch::Disable
1212 ================
1213 */
1216 }
1217 
1218 #ifdef CTF
1219 /*
1220 ===============================================================================
1221 
1222  idTrigger_Flag
1223 
1224 ===============================================================================
1225 */
1226 
1227 CLASS_DECLARATION( idTrigger_Multi, idTrigger_Flag )
1228  EVENT( EV_Touch, idTrigger_Flag::Event_Touch )
1229 END_CLASS
1230 
1231 idTrigger_Flag::idTrigger_Flag( void ) {
1232  team = -1;
1233  player = false;
1234  eventFlag = NULL;
1235 }
1236 
1237 void idTrigger_Flag::Spawn( void ) {
1238  team = spawnArgs.GetInt( "team", "0" );
1239  player = spawnArgs.GetBool( "player", "0" );
1240 
1241  idStr funcname = spawnArgs.GetString( "eventflag", "" );
1242  if ( funcname.Length() ) {
1243  eventFlag = idEventDef::FindEvent( funcname );// gameLocal.program.FindFunction( funcname );//, &idItemTeam::Type );
1244  if ( eventFlag == NULL ) {
1245  gameLocal.Warning( "trigger '%s' at (%s) event unknown '%s'", name.c_str(), GetPhysics()->GetOrigin().ToString(0), funcname.c_str() );
1246  }
1247  } else {
1248  eventFlag = NULL;
1249  }
1250 
1252 }
1253 
1254 void idTrigger_Flag::Event_Touch( idEntity *other, trace_t *trace ) {
1255 
1256  bool bTrigger = false;
1257  idItemTeam * flag = NULL;
1258 
1259  if ( player ) {
1260  if ( !other->IsType( idPlayer::Type ) )
1261  return;
1262 
1263  idPlayer * player = static_cast<idPlayer *>(other);
1264  if ( player->carryingFlag == false )
1265  return;
1266 
1267  if ( team != -1 && ( player->team != team || (player->team != 0 && player->team != 1)) )
1268  return;
1269 
1270  idItemTeam * flags[2];
1271 
1272  flags[0] = gameLocal.mpGame.GetTeamFlag( 0 );
1273  flags[1] = gameLocal.mpGame.GetTeamFlag( 1 );
1274 
1275  int iFriend = 1 - player->team; // index to the flag player team wants
1276  int iOpp = player->team; // index to the flag opp team wants
1277 
1278  // flag is captured if :
1279  // 1)flag is truely bound to the player
1280  // 2)opponent flag has been return
1281  if ( flags[iFriend]->carried && !flags[iFriend]->dropped && //flags[iFriend]->IsBoundTo( player ) &&
1282  !flags[iOpp]->carried && !flags[iOpp]->dropped )
1283  flag = flags[iFriend];
1284  else
1285  return;
1286  } else {
1287  if ( !other->IsType( idItemTeam::Type ) )
1288  return;
1289 
1290  idItemTeam * item = static_cast<idItemTeam *>( other );
1291 
1292  if ( item->team == team || team == -1 ) {
1293  flag = item;
1294  }
1295  else
1296  return;
1297  }
1298 
1299  if ( flag ) {
1300  switch ( eventFlag->GetNumArgs() ) {
1301  default :
1302  case 0 :
1303  flag->PostEventMS( eventFlag, 0 );
1304  break;
1305  case 1 :
1306  flag->PostEventMS( eventFlag, 0, 0 );
1307  break;
1308  case 2 :
1309  flag->PostEventMS( eventFlag, 0, 0, 0 );
1310  break;
1311  }
1312 
1313 /*
1314  ServerSendEvent( eventFlag->GetEventNum(), NULL, true, false );
1315 
1316  idThread *thread;
1317  if ( scriptFlag ) {
1318  thread = new idThread();
1319  thread->CallFunction( flag, scriptFlag, false );
1320  thread->DelayedStart( 0 );
1321  }
1322 */
1323  idTrigger_Multi::Event_Touch( other, trace );
1324  }
1325 }
1326 
1327 #endif
virtual const idVec3 & GetOrigin(int id=0) const =0
const idEventDef EV_ActivateTargets("activateTargets","e")
idPlayer * GetLocalPlayer() const
int ClipModelsTouchingBounds(const idBounds &bounds, int contentMask, idClipModel **clipModelList, int maxCount) const
Definition: Clip.cpp:804
idEntity * GetEntity(void) const
Definition: Clip.h:178
float random_delay
Definition: Trigger.h:98
virtual void EnableClip(void)=0
void TouchEntities(void)
Definition: Trigger.cpp:1137
float GetFloat(const char *key, const char *defaultString="0") const
Definition: Dict.h:248
void Event_Trigger(idEntity *activator)
Definition: Trigger.cpp:645
void WriteString(const char *string)
Definition: SaveGame.cpp:231
float Normalize(void)
Definition: Vector.h:646
idVec4 colorGreen
Definition: Lib.cpp:118
int GetInt(const char *key, const char *defaultString="0") const
Definition: Dict.h:252
bool PostEventSec(const idEventDef *ev, float time)
Definition: Class.cpp:747
virtual void SetContents(int contents, int id=-1)=0
void CallFunction(const function_t *func, bool clearStack)
virtual void DebugArrow(const idVec4 &color, const idVec3 &start, const idVec3 &end, int size, const int lifetime=0)=0
idVec3 GetCenter(void) const
Definition: Bounds.h:211
void Save(idSaveGame *savefile) const
Definition: Trigger.cpp:278
idClip clip
Definition: Game_local.h:296
idVec4 colorWhite
Definition: Lib.cpp:116
void Event_Trigger(idEntity *activator)
Definition: Trigger.cpp:432
#define MAX_GENTITIES
Definition: Game_local.h:83
void Spawn(void)
Definition: Trigger.cpp:223
void DelayedStart(int delay)
void Event_Trigger(idEntity *activator)
Definition: Trigger.cpp:907
void Event_Touch(idEntity *other, trace_t *trace)
Definition: Trigger.cpp:677
const idEventDef EV_Activate("activate","e")
void Event_Touch(idEntity *other, trace_t *trace)
Definition: Trigger.cpp:1002
void Restore(idRestoreGame *savefile)
Definition: Trigger.cpp:297
void Save(idSaveGame *savefile) const
Definition: Trigger.cpp:547
idRandom random
Definition: Game_local.h:291
int Length(void) const
Definition: Str.h:702
void void void void void Error(const char *fmt,...) const id_attribute((format(printf
Definition: Game_local.cpp:783
bool IsType(const idTypeInfo &c) const
Definition: Class.h:337
bool triggerWithSelf
Definition: Trigger.h:105
const idMat3 & GetAxis(void) const
Definition: Clip.h:210
void Restore(idRestoreGame *savefile)
Definition: Trigger.cpp:976
idList< idEntityPtr< idEntity > > targets
Definition: Entity.h:132
void Event_Timer(void)
Definition: Trigger.cpp:813
void CallScript(void) const
Definition: Trigger.cpp:142
virtual void Disable(void)
Definition: Trigger.cpp:1214
idClipModel * clipModel
Definition: Trigger.h:287
void Spawn(void)
Definition: Trigger.cpp:990
Definition: Vector.h:316
void ReadBool(bool &value)
Definition: SaveGame.cpp:976
void Event_Touch(idEntity *other, trace_t *trace)
Definition: Trigger.cpp:469
float wait
Definition: Trigger.h:95
void Event_TriggerAction(idEntity *activator)
Definition: Trigger.cpp:418
int team
Definition: Actor.h:115
const idVec3 & GetOrigin(void) const
Definition: Clip.h:206
void Spawn(void)
Definition: Trigger.cpp:1102
idDict spawnArgs
Definition: Entity.h:122
void TriggerAction(idEntity *activator)
Definition: Trigger.cpp:612
void WriteClipModel(const class idClipModel *clipModel)
Definition: SaveGame.cpp:744
int i
Definition: process.py:33
const char * Name(void) const
int Icmp(const char *text) const
Definition: Str.h:667
#define EVENT(event, function)
Definition: Class.h:53
idProgram program
Definition: Game_local.h:293
void WriteBool(const bool value)
Definition: SaveGame.cpp:222
void Event_Disable(void)
Definition: Trigger.cpp:205
float delay
Definition: Trigger.h:234
void void void Warning(const char *fmt,...) const id_attribute((format(printf
Definition: Game_local.cpp:735
int nextTriggerTime
Definition: Trigger.h:99
class idPlayerView playerView
Definition: Player.h:251
void Event_Use(idEntity *activator)
Definition: Trigger.cpp:827
virtual void Think(void)
Definition: Entity.cpp:891
GLuint GLuint GLsizei count
Definition: glext.h:2845
idVec4 colorYellow
Definition: Lib.cpp:120
static const idEventDef * FindEvent(const char *name)
Definition: Event.cpp:192
void Event_Toggle(idEntity *activator)
Definition: Trigger.cpp:1039
void Spawn(void)
Definition: Trigger.cpp:577
idPhysics * GetPhysics(void) const
Definition: Entity.cpp:2607
const char * GetString(const char *key, const char *defaultString="") const
Definition: Dict.h:240
void ReadFloat(float &value)
Definition: SaveGame.cpp:967
Definition: Vector.h:808
idVec3 ToForward(void) const
Definition: Angles.cpp:117
void Save(idSaveGame *savefile) const
Definition: Trigger.cpp:733
idVec3 vec3_origin(0.0f, 0.0f, 0.0f)
void WriteFloat(const float value)
Definition: SaveGame.cpp:213
const idEventDef EV_TriggerAction("<triggerAction>","e")
void Restore(idRestoreGame *savefile)
Definition: Trigger.cpp:747
cmHandle_t Handle(void) const
Definition: Clip.cpp:457
bool GetBool(const char *key, const char *defaultString="0") const
Definition: Dict.h:256
void Event_Trigger(idEntity *activator)
Definition: Trigger.cpp:1192
#define NULL
Definition: Lib.h:88
virtual void Enable(void)
Definition: Trigger.cpp:787
const idBounds & GetBounds(void) const
Definition: Clip.h:198
void Save(idSaveGame *savefile) const
Definition: Trigger.cpp:965
void Save(idSaveGame *savefile) const
Definition: Trigger.cpp:165
void Spawn(void)
Definition: Trigger.cpp:896
void CancelEvents(const idEventDef *ev)
Definition: Class.cpp:619
bool IsTraceModel(void) const
Definition: Clip.h:218
idStr offName
Definition: Trigger.h:177
void Save(idSaveGame *savefile) const
Definition: Trigger.cpp:874
bool triggerFirst
Definition: Trigger.h:104
virtual const idMat3 & GetAxis(int id=0) const =0
void Spawn(void)
Definition: Trigger.cpp:764
virtual void Enable(void)
Definition: Trigger.cpp:121
virtual void DrawText(const char *text, const idVec3 &origin, float scale, const idVec4 &color, const idMat3 &viewAxis, const int align=1, const int lifetime=0, bool depthTest=false)=0
void FromTransformedBounds(const idBounds &bounds, const idVec3 &origin, const idMat3 &axis)
Definition: Bounds.cpp:232
idLinkList< idEntity > spawnNode
Definition: Entity.h:114
bool CheckFacing(idEntity *activator)
Definition: Trigger.cpp:372
idGameLocal gameLocal
Definition: Game_local.cpp:64
const function_t * scriptFunction
Definition: Trigger.h:66
virtual void Damage(idEntity *inflictor, idEntity *attacker, const idVec3 &dir, const char *damageDefName, const float damageScale, const int location)
Definition: Entity.cpp:3061
#define END_CLASS
Definition: Class.h:54
idLinkList< idEntity > spawnedEntities
Definition: Game_local.h:281
void TriggerAction(idEntity *activator)
Definition: Trigger.cpp:393
virtual void DisableClip(void)=0
const char * ToString(int precision=2) const
Definition: Vector.cpp:221
void WriteInt(const int value)
Definition: SaveGame.cpp:168
#define SEC2MS(t)
Definition: Math.h:59
float random
Definition: Trigger.h:172
void ReadClipModel(idClipModel *&clipModel)
Definition: SaveGame.cpp:1519
idVec4 colorOrange
Definition: Lib.cpp:123
void Fade(idVec4 color, int time)
Definition: PlayerView.cpp:617
const idEventDef EV_Timer("<timer>", NULL)
idStr requires
Definition: Trigger.h:100
Definition: Matrix.h:333
void Restore(idRestoreGame *savefile)
Definition: Trigger.cpp:1128
#define show(x)
Definition: getpart.c:36
const idEventDef EV_Enable("enable", NULL)
idStr onName
Definition: Trigger.h:176
const function_t * GetScriptFunction(void) const
Definition: Trigger.cpp:156
tuple f
Definition: idal.py:89
idAngles viewAngles
Definition: Player.h:258
int Num(void) const
Definition: List.h:265
idMat3 ToMat3(void) const
Definition: Angles.cpp:199
virtual const idBounds & GetAbsBounds(int id=-1) const =0
const GLcharARB * name
Definition: glext.h:3629
#define RAD2DEG(a)
Definition: Math.h:57
int ContentsModel(const idVec3 &start, const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis)
Definition: Clip.cpp:1532
#define CLASS_DECLARATION(nameofsuperclass, nameofclass)
Definition: Class.h:110
Definition: Str.h:116
const char * GetName(void) const
Definition: Entity.cpp:875
virtual void SetClipModel(idClipModel *model, float density, int id=0, bool freeOld=true)=0
bool touchClient
Definition: Trigger.h:102
void Restore(idRestoreGame *savefile)
Definition: Trigger.cpp:178
void Event_Enable(void)
Definition: Trigger.cpp:196
const char * c_str(void) const
Definition: Str.h:487
bool RequirementMet(idEntity *activator, const idStr &requires, int removeItem)
void BecomeActive(int flags)
Definition: Entity.cpp:995
void Event_TriggerAction(idEntity *activator)
Definition: Trigger.cpp:927
const idEventDef EV_Remove("<immediateremove>", NULL)
virtual int GetContents(int id=-1) const =0
function_t * FindFunction(const char *name) const
float dot(float a[], float b[])
Definition: Model_lwo.cpp:3883
virtual void DebugBounds(const idVec4 &color, const idBounds &bounds, const idVec3 &org=vec3_origin, const int lifetime=0)=0
const char * GetEntityDefName(void) const
Definition: Entity.cpp:842
virtual void Disable(void)
Definition: Trigger.cpp:800
idRenderWorld * gameRenderWorld
Definition: Game_local.cpp:55
char * va(const char *fmt,...)
Definition: Str.cpp:1568
static float ACos(float a)
Definition: Math.h:544
void Spawn(void)
Definition: Trigger.cpp:323
bool PostEventMS(const idEventDef *ev, int time)
Definition: Class.cpp:666
void Restore(idRestoreGame *savefile)
Definition: Trigger.cpp:885
float delay
Definition: Trigger.h:97
idMultiplayerGame mpGame
Definition: Game_local.h:305
idStr name
Definition: Entity.h:121
int thinkFlags
Definition: Entity.h:125
const idEventDef EV_Touch("<touch>","et")
virtual void Think(void)
Definition: Trigger.cpp:1180
virtual void Enable(void)
Definition: Trigger.cpp:1205
float random
Definition: Trigger.h:96
void ReadString(idStr &string)
Definition: SaveGame.cpp:985
void Restore(idRestoreGame *savefile)
Definition: Trigger.cpp:562
void Event_TriggerAction(idEntity *activator)
Definition: Trigger.cpp:631
void BecomeInactive(int flags)
Definition: Entity.cpp:1025
const idEventDef EV_Disable("disable", NULL)
void ReadInt(int &value)
Definition: SaveGame.cpp:922
float CRandomFloat(void)
Definition: Random.h:86
void ActivateTargets(idEntity *activator) const
Definition: Entity.cpp:3650
void Save(idSaveGame *savefile)
Definition: Trigger.cpp:1119
bool touchOther
Definition: Trigger.h:103
virtual void Disable(void)
Definition: Trigger.cpp:131