doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Actor.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  idAnimState
38 
39 ***********************************************************************/
40 
41 /*
42 =====================
43 idAnimState::idAnimState
44 =====================
45 */
47  self = NULL;
48  animator = NULL;
49  thread = NULL;
50  idleAnim = true;
51  disabled = true;
53  animBlendFrames = 0;
55 }
56 
57 /*
58 =====================
59 idAnimState::~idAnimState
60 =====================
61 */
63  delete thread;
64 }
65 
66 /*
67 =====================
68 idAnimState::Save
69 =====================
70 */
71 void idAnimState::Save( idSaveGame *savefile ) const {
72 
73  savefile->WriteObject( self );
74 
75  // Save the entity owner of the animator
76  savefile->WriteObject( animator->GetEntity() );
77 
78  savefile->WriteObject( thread );
79 
80  savefile->WriteString( state );
81 
82  savefile->WriteInt( animBlendFrames );
83  savefile->WriteInt( lastAnimBlendFrames );
84  savefile->WriteInt( channel );
85  savefile->WriteBool( idleAnim );
86  savefile->WriteBool( disabled );
87 }
88 
89 /*
90 =====================
91 idAnimState::Restore
92 =====================
93 */
95  savefile->ReadObject( reinterpret_cast<idClass *&>( self ) );
96 
97  idEntity *animowner;
98  savefile->ReadObject( reinterpret_cast<idClass *&>( animowner ) );
99  if ( animowner ) {
100  animator = animowner->GetAnimator();
101  }
102 
103  savefile->ReadObject( reinterpret_cast<idClass *&>( thread ) );
104 
105  savefile->ReadString( state );
106 
107  savefile->ReadInt( animBlendFrames );
108  savefile->ReadInt( lastAnimBlendFrames );
109  savefile->ReadInt( channel );
110  savefile->ReadBool( idleAnim );
111  savefile->ReadBool( disabled );
112 }
113 
114 /*
115 =====================
116 idAnimState::Init
117 =====================
118 */
119 void idAnimState::Init( idActor *owner, idAnimator *_animator, int animchannel ) {
120  assert( owner );
121  assert( _animator );
122  self = owner;
123  animator = _animator;
124  channel = animchannel;
125 
126  if ( !thread ) {
127  thread = new idThread();
128  thread->ManualDelete();
129  }
130  thread->EndThread();
132 }
133 
134 /*
135 =====================
136 idAnimState::Shutdown
137 =====================
138 */
139 void idAnimState::Shutdown( void ) {
140  delete thread;
141  thread = NULL;
142 }
143 
144 /*
145 =====================
146 idAnimState::SetState
147 =====================
148 */
149 void idAnimState::SetState( const char *statename, int blendFrames ) {
150  const function_t *func;
151 
152  func = self->scriptObject.GetFunction( statename );
153  if ( !func ) {
154  assert( 0 );
155  gameLocal.Error( "Can't find function '%s' in object '%s'", statename, self->scriptObject.GetTypeName() );
156  }
157 
158  state = statename;
159  disabled = false;
160  animBlendFrames = blendFrames;
161  lastAnimBlendFrames = blendFrames;
162  thread->CallFunction( self, func, true );
163 
164  animBlendFrames = blendFrames;
165  lastAnimBlendFrames = blendFrames;
166  disabled = false;
167  idleAnim = false;
168 
169  if ( ai_debugScript.GetInteger() == self->entityNumber ) {
170  gameLocal.Printf( "%d: %s: Animstate: %s\n", gameLocal.time, self->name.c_str(), state.c_str() );
171  }
172 }
173 
174 /*
175 =====================
176 idAnimState::StopAnim
177 =====================
178 */
179 void idAnimState::StopAnim( int frames ) {
180  animBlendFrames = 0;
181  animator->Clear( channel, gameLocal.time, FRAME2MS( frames ) );
182 }
183 
184 /*
185 =====================
186 idAnimState::PlayAnim
187 =====================
188 */
189 void idAnimState::PlayAnim( int anim ) {
190  if ( anim ) {
192  }
193  animBlendFrames = 0;
194 }
195 
196 /*
197 =====================
198 idAnimState::CycleAnim
199 =====================
200 */
201 void idAnimState::CycleAnim( int anim ) {
202  if ( anim ) {
204  }
205  animBlendFrames = 0;
206 }
207 
208 /*
209 =====================
210 idAnimState::BecomeIdle
211 =====================
212 */
214  idleAnim = true;
215 }
216 
217 /*
218 =====================
219 idAnimState::Disabled
220 =====================
221 */
222 bool idAnimState::Disabled( void ) const {
223  return disabled;
224 }
225 
226 /*
227 =====================
228 idAnimState::AnimDone
229 =====================
230 */
231 bool idAnimState::AnimDone( int blendFrames ) const {
232  int animDoneTime;
233 
234  animDoneTime = animator->CurrentAnim( channel )->GetEndTime();
235  if ( animDoneTime < 0 ) {
236  // playing a cycle
237  return false;
238  } else if ( animDoneTime - FRAME2MS( blendFrames ) <= gameLocal.time ) {
239  return true;
240  } else {
241  return false;
242  }
243 }
244 
245 /*
246 =====================
247 idAnimState::IsIdle
248 =====================
249 */
250 bool idAnimState::IsIdle( void ) const {
251  return disabled || idleAnim;
252 }
253 
254 /*
255 =====================
256 idAnimState::GetAnimFlags
257 =====================
258 */
260  animFlags_t flags;
261 
262  memset( &flags, 0, sizeof( flags ) );
263  if ( !disabled && !AnimDone( 0 ) ) {
265  }
266 
267  return flags;
268 }
269 
270 /*
271 =====================
272 idAnimState::Enable
273 =====================
274 */
275 void idAnimState::Enable( int blendFrames ) {
276  if ( disabled ) {
277  disabled = false;
278  animBlendFrames = blendFrames;
279  lastAnimBlendFrames = blendFrames;
280  if ( state.Length() ) {
281  SetState( state.c_str(), blendFrames );
282  }
283  }
284 }
285 
286 /*
287 =====================
288 idAnimState::Disable
289 =====================
290 */
291 void idAnimState::Disable( void ) {
292  disabled = true;
293  idleAnim = false;
294 }
295 
296 /*
297 =====================
298 idAnimState::UpdateState
299 =====================
300 */
302  if ( disabled ) {
303  return false;
304  }
305 
306  if ( ai_debugScript.GetInteger() == self->entityNumber ) {
308  } else {
310  }
311 
312  thread->Execute();
313 
314  return true;
315 }
316 
317 /***********************************************************************
318 
319  idActor
320 
321 ***********************************************************************/
322 
323 const idEventDef AI_EnableEyeFocus( "enableEyeFocus" );
324 const idEventDef AI_DisableEyeFocus( "disableEyeFocus" );
325 const idEventDef EV_Footstep( "footstep" );
326 const idEventDef EV_FootstepLeft( "leftFoot" );
327 const idEventDef EV_FootstepRight( "rightFoot" );
328 const idEventDef EV_EnableWalkIK( "EnableWalkIK" );
329 const idEventDef EV_DisableWalkIK( "DisableWalkIK" );
330 const idEventDef EV_EnableLegIK( "EnableLegIK", "d" );
331 const idEventDef EV_DisableLegIK( "DisableLegIK", "d" );
332 const idEventDef AI_StopAnim( "stopAnim", "dd" );
333 const idEventDef AI_PlayAnim( "playAnim", "ds", 'd' );
334 const idEventDef AI_PlayCycle( "playCycle", "ds", 'd' );
335 const idEventDef AI_IdleAnim( "idleAnim", "ds", 'd' );
336 const idEventDef AI_SetSyncedAnimWeight( "setSyncedAnimWeight", "ddf" );
337 const idEventDef AI_SetBlendFrames( "setBlendFrames", "dd" );
338 const idEventDef AI_GetBlendFrames( "getBlendFrames", "d", 'd' );
339 const idEventDef AI_AnimState( "animState", "dsd" );
340 const idEventDef AI_GetAnimState( "getAnimState", "d", 's' );
341 const idEventDef AI_InAnimState( "inAnimState", "ds", 'd' );
342 const idEventDef AI_FinishAction( "finishAction", "s" );
343 const idEventDef AI_AnimDone( "animDone", "dd", 'd' );
344 const idEventDef AI_OverrideAnim( "overrideAnim", "d" );
345 const idEventDef AI_EnableAnim( "enableAnim", "dd" );
346 const idEventDef AI_PreventPain( "preventPain", "f" );
347 const idEventDef AI_DisablePain( "disablePain" );
348 const idEventDef AI_EnablePain( "enablePain" );
349 const idEventDef AI_GetPainAnim( "getPainAnim", NULL, 's' );
350 const idEventDef AI_SetAnimPrefix( "setAnimPrefix", "s" );
351 const idEventDef AI_HasAnim( "hasAnim", "ds", 'f' );
352 const idEventDef AI_CheckAnim( "checkAnim", "ds" );
353 const idEventDef AI_ChooseAnim( "chooseAnim", "ds", 's' );
354 const idEventDef AI_AnimLength( "animLength", "ds", 'f' );
355 const idEventDef AI_AnimDistance( "animDistance", "ds", 'f' );
356 const idEventDef AI_HasEnemies( "hasEnemies", NULL, 'd' );
357 const idEventDef AI_NextEnemy( "nextEnemy", "E", 'e' );
358 const idEventDef AI_ClosestEnemyToPoint( "closestEnemyToPoint", "v", 'e' );
359 const idEventDef AI_SetNextState( "setNextState", "s" );
360 const idEventDef AI_SetState( "setState", "s" );
361 const idEventDef AI_GetState( "getState", NULL, 's' );
362 const idEventDef AI_GetHead( "getHead", NULL, 'e' );
363 #ifdef _D3XP
364 const idEventDef EV_SetDamageGroupScale( "setDamageGroupScale", "sf" );
365 const idEventDef EV_SetDamageGroupScaleAll( "setDamageGroupScaleAll", "f" );
366 const idEventDef EV_GetDamageGroupScale( "getDamageGroupScale", "s", 'f' );
367 const idEventDef EV_SetDamageCap( "setDamageCap", "f" );
368 const idEventDef EV_SetWaitState( "setWaitState" , "s" );
369 const idEventDef EV_GetWaitState( "getWaitState", NULL, 's' );
370 #endif
371 
373  EVENT( AI_EnableEyeFocus, idActor::Event_EnableEyeFocus )
374  EVENT( AI_DisableEyeFocus, idActor::Event_DisableEyeFocus )
375  EVENT( EV_Footstep, idActor::Event_Footstep )
376  EVENT( EV_FootstepLeft, idActor::Event_Footstep )
377  EVENT( EV_FootstepRight, idActor::Event_Footstep )
378  EVENT( EV_EnableWalkIK, idActor::Event_EnableWalkIK )
379  EVENT( EV_DisableWalkIK, idActor::Event_DisableWalkIK )
380  EVENT( EV_EnableLegIK, idActor::Event_EnableLegIK )
381  EVENT( EV_DisableLegIK, idActor::Event_DisableLegIK )
382  EVENT( AI_PreventPain, idActor::Event_PreventPain )
383  EVENT( AI_DisablePain, idActor::Event_DisablePain )
384  EVENT( AI_EnablePain, idActor::Event_EnablePain )
385  EVENT( AI_GetPainAnim, idActor::Event_GetPainAnim )
386  EVENT( AI_SetAnimPrefix, idActor::Event_SetAnimPrefix )
387  EVENT( AI_StopAnim, idActor::Event_StopAnim )
388  EVENT( AI_PlayAnim, idActor::Event_PlayAnim )
389  EVENT( AI_PlayCycle, idActor::Event_PlayCycle )
390  EVENT( AI_IdleAnim, idActor::Event_IdleAnim )
391  EVENT( AI_SetSyncedAnimWeight, idActor::Event_SetSyncedAnimWeight )
392  EVENT( AI_SetBlendFrames, idActor::Event_SetBlendFrames )
393  EVENT( AI_GetBlendFrames, idActor::Event_GetBlendFrames )
394  EVENT( AI_AnimState, idActor::Event_AnimState )
395  EVENT( AI_GetAnimState, idActor::Event_GetAnimState )
396  EVENT( AI_InAnimState, idActor::Event_InAnimState )
397  EVENT( AI_FinishAction, idActor::Event_FinishAction )
398  EVENT( AI_AnimDone, idActor::Event_AnimDone )
399  EVENT( AI_OverrideAnim, idActor::Event_OverrideAnim )
400  EVENT( AI_EnableAnim, idActor::Event_EnableAnim )
401  EVENT( AI_HasAnim, idActor::Event_HasAnim )
402  EVENT( AI_CheckAnim, idActor::Event_CheckAnim )
403  EVENT( AI_ChooseAnim, idActor::Event_ChooseAnim )
404  EVENT( AI_AnimLength, idActor::Event_AnimLength )
405  EVENT( AI_AnimDistance, idActor::Event_AnimDistance )
406  EVENT( AI_HasEnemies, idActor::Event_HasEnemies )
407  EVENT( AI_NextEnemy, idActor::Event_NextEnemy )
408  EVENT( AI_ClosestEnemyToPoint, idActor::Event_ClosestEnemyToPoint )
409  EVENT( EV_StopSound, idActor::Event_StopSound )
410  EVENT( AI_SetNextState, idActor::Event_SetNextState )
411  EVENT( AI_SetState, idActor::Event_SetState )
412  EVENT( AI_GetState, idActor::Event_GetState )
413  EVENT( AI_GetHead, idActor::Event_GetHead )
414 #ifdef _D3XP
415  EVENT( EV_SetDamageGroupScale, idActor::Event_SetDamageGroupScale )
416  EVENT( EV_SetDamageGroupScaleAll, idActor::Event_SetDamageGroupScaleAll )
417  EVENT( EV_GetDamageGroupScale, idActor::Event_GetDamageGroupScale )
418  EVENT( EV_SetDamageCap, idActor::Event_SetDamageCap )
419  EVENT( EV_SetWaitState, idActor::Event_SetWaitState )
420  EVENT( EV_GetWaitState, idActor::Event_GetWaitState )
421 #endif
422 END_CLASS
423 
424 /*
425 =====================
426 idActor::idActor
427 =====================
428 */
430  viewAxis.Identity();
431 
432  scriptThread = NULL; // initialized by ConstructScriptObject, which is called by idEntity::Spawn
433 
434  use_combat_bbox = false;
435  head = NULL;
436 
437  team = 0;
438  rank = 0;
439  fovDot = 0.0f;
440  eyeOffset.Zero();
441  pain_debounce_time = 0;
442  pain_delay = 0;
443  pain_threshold = 0;
444 
445  state = NULL;
446  idealState = NULL;
447 
451 
452  modelOffset.Zero();
454 
455  painTime = 0;
456  allowPain = false;
457  allowEyeFocus = false;
458 
459  waitState = "";
460 
461  blink_anim = 0;
462  blink_time = 0;
463  blink_min = 0;
464  blink_max = 0;
465 
466  finalBoss = false;
467 
469 
470  enemyNode.SetOwner( this );
471  enemyList.SetOwner( this );
472 
473 #ifdef _D3XP
474  damageCap = -1;
475 #endif
476 }
477 
478 /*
479 =====================
480 idActor::~idActor
481 =====================
482 */
484  int i;
485  idEntity *ent;
486 
488  scriptObject.Free();
489 
490  StopSound( SND_CHANNEL_ANY, false );
491 
492  delete combatModel;
493  combatModel = NULL;
494 
495  if ( head.GetEntity() ) {
496  head.GetEntity()->ClearBody();
498  }
499 
500  // remove any attached entities
501  for( i = 0; i < attachments.Num(); i++ ) {
502  ent = attachments[ i ].ent.GetEntity();
503  if ( ent ) {
504  ent->PostEventMS( &EV_Remove, 0 );
505  }
506  }
507 
508  ShutdownThreads();
509 }
510 
511 /*
512 =====================
513 idActor::Spawn
514 =====================
515 */
516 void idActor::Spawn( void ) {
517  idEntity *ent;
518  idStr jointName;
519  float fovDegrees;
520  copyJoints_t copyJoint;
521 
522  animPrefix = "";
523  state = NULL;
524  idealState = NULL;
525 
526  spawnArgs.GetInt( "rank", "0", rank );
527  spawnArgs.GetInt( "team", "0", team );
528  spawnArgs.GetVector( "offsetModel", "0 0 0", modelOffset );
529 
530  spawnArgs.GetBool( "use_combat_bbox", "0", use_combat_bbox );
531 
532  viewAxis = GetPhysics()->GetAxis();
533 
534  spawnArgs.GetFloat( "fov", "90", fovDegrees );
535  SetFOV( fovDegrees );
536 
537  pain_debounce_time = 0;
538 
539  pain_delay = SEC2MS( spawnArgs.GetFloat( "pain_delay" ) );
540  pain_threshold = spawnArgs.GetInt( "pain_threshold" );
541 
542  LoadAF();
543 
544  walkIK.Init( this, IK_ANIM, modelOffset );
545 
546  // the animation used to be set to the IK_ANIM at this point, but that was fixed, resulting in
547  // attachments not binding correctly, so we're stuck setting the IK_ANIM before attaching things.
550 
551  // spawn any attachments we might have
552  const idKeyValue *kv = spawnArgs.MatchPrefix( "def_attach", NULL );
553  while ( kv ) {
554  idDict args;
555 
556  args.Set( "classname", kv->GetValue().c_str() );
557 
558  // make items non-touchable so the player can't take them out of the character's hands
559  args.Set( "no_touch", "1" );
560 
561  // don't let them drop to the floor
562  args.Set( "dropToFloor", "0" );
563 
564  gameLocal.SpawnEntityDef( args, &ent );
565  if ( !ent ) {
566  gameLocal.Error( "Couldn't spawn '%s' to attach to entity '%s'", kv->GetValue().c_str(), name.c_str() );
567  } else {
568  Attach( ent );
569  }
570  kv = spawnArgs.MatchPrefix( "def_attach", kv );
571  }
572 
574  SetupHead();
575 
576  // clear the bind anim
578 
579  idEntity *headEnt = head.GetEntity();
580  idAnimator *headAnimator;
581  if ( headEnt ) {
582  headAnimator = headEnt->GetAnimator();
583  } else {
584  headAnimator = &animator;
585  }
586 
587  if ( headEnt ) {
588  // set up the list of joints to copy to the head
589  for( kv = spawnArgs.MatchPrefix( "copy_joint", NULL ); kv != NULL; kv = spawnArgs.MatchPrefix( "copy_joint", kv ) ) {
590  if ( kv->GetValue() == "" ) {
591  // probably clearing out inherited key, so skip it
592  continue;
593  }
594 
595  jointName = kv->GetKey();
596  if ( jointName.StripLeadingOnce( "copy_joint_world " ) ) {
597  copyJoint.mod = JOINTMOD_WORLD_OVERRIDE;
598  } else {
599  jointName.StripLeadingOnce( "copy_joint " );
600  copyJoint.mod = JOINTMOD_LOCAL_OVERRIDE;
601  }
602 
603  copyJoint.from = animator.GetJointHandle( jointName );
604  if ( copyJoint.from == INVALID_JOINT ) {
605  gameLocal.Warning( "Unknown copy_joint '%s' on entity %s", jointName.c_str(), name.c_str() );
606  continue;
607  }
608 
609  jointName = kv->GetValue();
610  copyJoint.to = headAnimator->GetJointHandle( jointName );
611  if ( copyJoint.to == INVALID_JOINT ) {
612  gameLocal.Warning( "Unknown copy_joint '%s' on head of entity %s", jointName.c_str(), name.c_str() );
613  continue;
614  }
615 
616  copyJoints.Append( copyJoint );
617  }
618  }
619 
620  // set up blinking
621  blink_anim = headAnimator->GetAnim( "blink" );
622  blink_time = 0; // it's ok to blink right away
623  blink_min = SEC2MS( spawnArgs.GetFloat( "blink_min", "0.5" ) );
624  blink_max = SEC2MS( spawnArgs.GetFloat( "blink_max", "8" ) );
625 
626  // set up the head anim if necessary
627  int headAnim = headAnimator->GetAnim( "def_head" );
628  if ( headAnim ) {
629  if ( headEnt ) {
630  headAnimator->CycleAnim( ANIMCHANNEL_ALL, headAnim, gameLocal.time, 0 );
631  } else {
632  headAnimator->CycleAnim( ANIMCHANNEL_HEAD, headAnim, gameLocal.time, 0 );
633  }
634  }
635 
636  if ( spawnArgs.GetString( "sound_bone", "", jointName ) ) {
637  soundJoint = animator.GetJointHandle( jointName );
638  if ( soundJoint == INVALID_JOINT ) {
639  gameLocal.Warning( "idAnimated '%s' at (%s): cannot find joint '%s' for sound playback", name.c_str(), GetPhysics()->GetOrigin().ToString(0), jointName.c_str() );
640  }
641  }
642 
643  finalBoss = spawnArgs.GetBool( "finalBoss" );
644 
645  FinishSetup();
646 }
647 
648 /*
649 ================
650 idActor::FinishSetup
651 ================
652 */
653 void idActor::FinishSetup( void ) {
654  const char *scriptObjectName;
655 
656  // setup script object
657  if ( spawnArgs.GetString( "scriptobject", NULL, &scriptObjectName ) ) {
658  if ( !scriptObject.SetType( scriptObjectName ) ) {
659  gameLocal.Error( "Script object '%s' not found on entity '%s'.", scriptObjectName, name.c_str() );
660  }
661 
663  }
664 
665  SetupBody();
666 }
667 
668 /*
669 ================
670 idActor::SetupHead
671 ================
672 */
673 void idActor::SetupHead( void ) {
674  idAFAttachment *headEnt;
675  idStr jointName;
676  const char *headModel;
677  jointHandle_t joint;
678  jointHandle_t damageJoint;
679  int i;
680  const idKeyValue *sndKV;
681 
682  if ( gameLocal.isClient ) {
683  return;
684  }
685 
686  headModel = spawnArgs.GetString( "def_head", "" );
687  if ( headModel[ 0 ] ) {
688  jointName = spawnArgs.GetString( "head_joint" );
689  joint = animator.GetJointHandle( jointName );
690  if ( joint == INVALID_JOINT ) {
691  gameLocal.Error( "Joint '%s' not found for 'head_joint' on '%s'", jointName.c_str(), name.c_str() );
692  }
693 
694  // set the damage joint to be part of the head damage group
695  damageJoint = joint;
696  for( i = 0; i < damageGroups.Num(); i++ ) {
697  if ( damageGroups[ i ] == "head" ) {
698  damageJoint = static_cast<jointHandle_t>( i );
699  break;
700  }
701  }
702 
703  // copy any sounds in case we have frame commands on the head
704  idDict args;
705  sndKV = spawnArgs.MatchPrefix( "snd_", NULL );
706  while( sndKV ) {
707  args.Set( sndKV->GetKey(), sndKV->GetValue() );
708  sndKV = spawnArgs.MatchPrefix( "snd_", sndKV );
709  }
710 
711 #ifdef _D3XP
712  // copy slowmo param to the head
713  args.SetBool( "slowmo", spawnArgs.GetBool("slowmo", "1") );
714 #endif
715 
716 
717  headEnt = static_cast<idAFAttachment *>( gameLocal.SpawnEntityType( idAFAttachment::Type, &args ) );
718  headEnt->SetName( va( "%s_head", name.c_str() ) );
719  headEnt->SetBody( this, headModel, damageJoint );
720  head = headEnt;
721 
722 #ifdef _D3XP
723  idStr xSkin;
724  if ( spawnArgs.GetString( "skin_head_xray", "", xSkin ) ) {
725  headEnt->xraySkin = declManager->FindSkin( xSkin.c_str() );
726  headEnt->UpdateModel();
727  }
728 #endif
729 
730  idVec3 origin;
731  idMat3 axis;
732  idAttachInfo &attach = attachments.Alloc();
733  attach.channel = animator.GetChannelForJoint( joint );
734  animator.GetJointTransform( joint, gameLocal.time, origin, axis );
735  origin = renderEntity.origin + ( origin + modelOffset ) * renderEntity.axis;
736  attach.ent = headEnt;
737  headEnt->SetOrigin( origin );
738  headEnt->SetAxis( renderEntity.axis );
739  headEnt->BindToJoint( this, joint, true );
740  }
741 }
742 
743 /*
744 ================
745 idActor::CopyJointsFromBodyToHead
746 ================
747 */
749  idEntity *headEnt = head.GetEntity();
750  idAnimator *headAnimator;
751  int i;
752  idMat3 mat;
753  idMat3 axis;
754  idVec3 pos;
755 
756  if ( !headEnt ) {
757  return;
758  }
759 
760  headAnimator = headEnt->GetAnimator();
761 
762  // copy the animation from the body to the head
763  for( i = 0; i < copyJoints.Num(); i++ ) {
764  if ( copyJoints[ i ].mod == JOINTMOD_WORLD_OVERRIDE ) {
765  mat = headEnt->GetPhysics()->GetAxis().Transpose();
766  GetJointWorldTransform( copyJoints[ i ].from, gameLocal.time, pos, axis );
767  pos -= headEnt->GetPhysics()->GetOrigin();
768  headAnimator->SetJointPos( copyJoints[ i ].to, copyJoints[ i ].mod, pos * mat );
769  headAnimator->SetJointAxis( copyJoints[ i ].to, copyJoints[ i ].mod, axis * mat );
770  } else {
771  animator.GetJointLocalTransform( copyJoints[ i ].from, gameLocal.time, pos, axis );
772  headAnimator->SetJointPos( copyJoints[ i ].to, copyJoints[ i ].mod, pos );
773  headAnimator->SetJointAxis( copyJoints[ i ].to, copyJoints[ i ].mod, axis );
774  }
775  }
776 }
777 
778 /*
779 ================
780 idActor::Restart
781 ================
782 */
783 void idActor::Restart( void ) {
784  assert( !head.GetEntity() );
785  SetupHead();
786  FinishSetup();
787 }
788 
789 /*
790 ================
791 idActor::Save
792 
793 archive object for savegame file
794 ================
795 */
796 void idActor::Save( idSaveGame *savefile ) const {
797  idActor *ent;
798  int i;
799 
800  savefile->WriteInt( team );
801  savefile->WriteInt( rank );
802  savefile->WriteMat3( viewAxis );
803 
804  savefile->WriteInt( enemyList.Num() );
805  for ( ent = enemyList.Next(); ent != NULL; ent = ent->enemyNode.Next() ) {
806  savefile->WriteObject( ent );
807  }
808 
809  savefile->WriteFloat( fovDot );
810  savefile->WriteVec3( eyeOffset );
811  savefile->WriteVec3( modelOffset );
812  savefile->WriteAngles( deltaViewAngles );
813 
814  savefile->WriteInt( pain_debounce_time );
815  savefile->WriteInt( pain_delay );
816  savefile->WriteInt( pain_threshold );
817 
818  savefile->WriteInt( damageGroups.Num() );
819  for( i = 0; i < damageGroups.Num(); i++ ) {
820  savefile->WriteString( damageGroups[ i ] );
821  }
822 
823  savefile->WriteInt( damageScale.Num() );
824  for( i = 0; i < damageScale.Num(); i++ ) {
825  savefile->WriteFloat( damageScale[ i ] );
826  }
827 
828  savefile->WriteBool( use_combat_bbox );
829  head.Save( savefile );
830 
831  savefile->WriteInt( copyJoints.Num() );
832  for( i = 0; i < copyJoints.Num(); i++ ) {
833  savefile->WriteInt( copyJoints[i].mod );
834  savefile->WriteJoint( copyJoints[i].from );
835  savefile->WriteJoint( copyJoints[i].to );
836  }
837 
838  savefile->WriteJoint( leftEyeJoint );
839  savefile->WriteJoint( rightEyeJoint );
840  savefile->WriteJoint( soundJoint );
841 
842  walkIK.Save( savefile );
843 
844  savefile->WriteString( animPrefix );
845  savefile->WriteString( painAnim );
846 
847  savefile->WriteInt( blink_anim );
848  savefile->WriteInt( blink_time );
849  savefile->WriteInt( blink_min );
850  savefile->WriteInt( blink_max );
851 
852  // script variables
853  savefile->WriteObject( scriptThread );
854 
855  savefile->WriteString( waitState );
856 
857  headAnim.Save( savefile );
858  torsoAnim.Save( savefile );
859  legsAnim.Save( savefile );
860 
861  savefile->WriteBool( allowPain );
862  savefile->WriteBool( allowEyeFocus );
863 
864  savefile->WriteInt( painTime );
865 
866  savefile->WriteInt( attachments.Num() );
867  for ( i = 0; i < attachments.Num(); i++ ) {
868  attachments[i].ent.Save( savefile );
869  savefile->WriteInt( attachments[i].channel );
870  }
871 
872  savefile->WriteBool( finalBoss );
873 
874  idToken token;
875 
876  //FIXME: this is unneccesary
877  if ( state ) {
878  idLexer src( state->Name(), idStr::Length( state->Name() ), "idAI::Save" );
879 
880  src.ReadTokenOnLine( &token );
881  src.ExpectTokenString( "::" );
882  src.ReadTokenOnLine( &token );
883 
884  savefile->WriteString( token );
885  } else {
886  savefile->WriteString( "" );
887  }
888 
889  if ( idealState ) {
890  idLexer src( idealState->Name(), idStr::Length( idealState->Name() ), "idAI::Save" );
891 
892  src.ReadTokenOnLine( &token );
893  src.ExpectTokenString( "::" );
894  src.ReadTokenOnLine( &token );
895 
896  savefile->WriteString( token );
897  } else {
898  savefile->WriteString( "" );
899  }
900 
901 #ifdef _D3XP
902  savefile->WriteInt(damageCap);
903 #endif
904 
905 }
906 
907 /*
908 ================
909 idActor::Restore
910 
911 unarchives object from save game file
912 ================
913 */
914 void idActor::Restore( idRestoreGame *savefile ) {
915  int i, num;
916  idActor *ent;
917 
918  savefile->ReadInt( team );
919  savefile->ReadInt( rank );
920  savefile->ReadMat3( viewAxis );
921 
922  savefile->ReadInt( num );
923  for ( i = 0; i < num; i++ ) {
924  savefile->ReadObject( reinterpret_cast<idClass *&>( ent ) );
925  assert( ent );
926  if ( ent ) {
927  ent->enemyNode.AddToEnd( enemyList );
928  }
929  }
930 
931  savefile->ReadFloat( fovDot );
932  savefile->ReadVec3( eyeOffset );
933  savefile->ReadVec3( modelOffset );
934  savefile->ReadAngles( deltaViewAngles );
935 
936  savefile->ReadInt( pain_debounce_time );
937  savefile->ReadInt( pain_delay );
938  savefile->ReadInt( pain_threshold );
939 
940  savefile->ReadInt( num );
942  damageGroups.SetNum( num );
943  for( i = 0; i < num; i++ ) {
944  savefile->ReadString( damageGroups[ i ] );
945  }
946 
947  savefile->ReadInt( num );
948  damageScale.SetNum( num );
949  for( i = 0; i < num; i++ ) {
950  savefile->ReadFloat( damageScale[ i ] );
951  }
952 
953  savefile->ReadBool( use_combat_bbox );
954  head.Restore( savefile );
955 
956  savefile->ReadInt( num );
957  copyJoints.SetNum( num );
958  for( i = 0; i < num; i++ ) {
959  int val;
960  savefile->ReadInt( val );
961  copyJoints[i].mod = static_cast<jointModTransform_t>( val );
962  savefile->ReadJoint( copyJoints[i].from );
963  savefile->ReadJoint( copyJoints[i].to );
964  }
965 
966  savefile->ReadJoint( leftEyeJoint );
967  savefile->ReadJoint( rightEyeJoint );
968  savefile->ReadJoint( soundJoint );
969 
970  walkIK.Restore( savefile );
971 
972  savefile->ReadString( animPrefix );
973  savefile->ReadString( painAnim );
974 
975  savefile->ReadInt( blink_anim );
976  savefile->ReadInt( blink_time );
977  savefile->ReadInt( blink_min );
978  savefile->ReadInt( blink_max );
979 
980  savefile->ReadObject( reinterpret_cast<idClass *&>( scriptThread ) );
981 
982  savefile->ReadString( waitState );
983 
984  headAnim.Restore( savefile );
985  torsoAnim.Restore( savefile );
986  legsAnim.Restore( savefile );
987 
988  savefile->ReadBool( allowPain );
989  savefile->ReadBool( allowEyeFocus );
990 
991  savefile->ReadInt( painTime );
992 
993  savefile->ReadInt( num );
994  for ( i = 0; i < num; i++ ) {
995  idAttachInfo &attach = attachments.Alloc();
996  attach.ent.Restore( savefile );
997  savefile->ReadInt( attach.channel );
998  }
999 
1000  savefile->ReadBool( finalBoss );
1001 
1002  idStr statename;
1003 
1004  savefile->ReadString( statename );
1005  if ( statename.Length() > 0 ) {
1006  state = GetScriptFunction( statename );
1007  }
1008 
1009  savefile->ReadString( statename );
1010  if ( statename.Length() > 0 ) {
1011  idealState = GetScriptFunction( statename );
1012  }
1013 
1014 #ifdef _D3XP
1015  savefile->ReadInt(damageCap);
1016 #endif
1017 }
1018 
1019 /*
1020 ================
1021 idActor::Hide
1022 ================
1023 */
1024 void idActor::Hide( void ) {
1025  idEntity *ent;
1026  idEntity *next;
1027 
1029  if ( head.GetEntity() ) {
1030  head.GetEntity()->Hide();
1031  }
1032 
1033  for( ent = GetNextTeamEntity(); ent != NULL; ent = next ) {
1034  next = ent->GetNextTeamEntity();
1035  if ( ent->GetBindMaster() == this ) {
1036  ent->Hide();
1037  if ( ent->IsType( idLight::Type ) ) {
1038  static_cast<idLight *>( ent )->Off();
1039  }
1040  }
1041  }
1042  UnlinkCombat();
1043 }
1044 
1045 /*
1046 ================
1047 idActor::Show
1048 ================
1049 */
1050 void idActor::Show( void ) {
1051  idEntity *ent;
1052  idEntity *next;
1053 
1055  if ( head.GetEntity() ) {
1056  head.GetEntity()->Show();
1057  }
1058  for( ent = GetNextTeamEntity(); ent != NULL; ent = next ) {
1059  next = ent->GetNextTeamEntity();
1060  if ( ent->GetBindMaster() == this ) {
1061  ent->Show();
1062  if ( ent->IsType( idLight::Type ) ) {
1063 #ifdef _D3XP
1064  if(!spawnArgs.GetBool("lights_off", "0")) {
1065  static_cast<idLight *>( ent )->On();
1066  }
1067 #endif
1068 
1069 
1070  }
1071  }
1072  }
1073  LinkCombat();
1074 }
1075 
1076 /*
1077 ==============
1078 idActor::GetDefaultSurfaceType
1079 ==============
1080 */
1082  return SURFTYPE_FLESH;
1083 }
1084 
1085 /*
1086 ================
1087 idActor::ProjectOverlay
1088 ================
1089 */
1090 void idActor::ProjectOverlay( const idVec3 &origin, const idVec3 &dir, float size, const char *material ) {
1091  idEntity *ent;
1092  idEntity *next;
1093 
1094  idEntity::ProjectOverlay( origin, dir, size, material );
1095 
1096  for( ent = GetNextTeamEntity(); ent != NULL; ent = next ) {
1097  next = ent->GetNextTeamEntity();
1098  if ( ent->GetBindMaster() == this ) {
1099  if ( ent->fl.takedamage && ent->spawnArgs.GetBool( "bleed" ) ) {
1100  ent->ProjectOverlay( origin, dir, size, material );
1101  }
1102  }
1103  }
1104 }
1105 
1106 /*
1107 ================
1108 idActor::LoadAF
1109 ================
1110 */
1111 bool idActor::LoadAF( void ) {
1112  idStr fileName;
1113 
1114  if ( !spawnArgs.GetString( "ragdoll", "*unknown*", fileName ) || !fileName.Length() ) {
1115  return false;
1116  }
1117  af.SetAnimator( GetAnimator() );
1118  return af.Load( this, fileName );
1119 }
1120 
1121 /*
1122 =====================
1123 idActor::SetupBody
1124 =====================
1125 */
1126 void idActor::SetupBody( void ) {
1127  const char *jointname;
1128 
1131 
1132  idEntity *headEnt = head.GetEntity();
1133  if ( headEnt ) {
1134  jointname = spawnArgs.GetString( "bone_leftEye" );
1135  leftEyeJoint = headEnt->GetAnimator()->GetJointHandle( jointname );
1136 
1137  jointname = spawnArgs.GetString( "bone_rightEye" );
1138  rightEyeJoint = headEnt->GetAnimator()->GetJointHandle( jointname );
1139 
1140  // set up the eye height. check if it's specified in the def.
1141  if ( !spawnArgs.GetFloat( "eye_height", "0", eyeOffset.z ) ) {
1142  // if not in the def, then try to base it off the idle animation
1143  int anim = headEnt->GetAnimator()->GetAnim( "idle" );
1144  if ( anim && ( leftEyeJoint != INVALID_JOINT ) ) {
1145  idVec3 pos;
1146  idMat3 axis;
1147  headEnt->GetAnimator()->PlayAnim( ANIMCHANNEL_ALL, anim, gameLocal.time, 0 );
1148  headEnt->GetAnimator()->GetJointTransform( leftEyeJoint, gameLocal.time, pos, axis );
1149  headEnt->GetAnimator()->ClearAllAnims( gameLocal.time, 0 );
1150  headEnt->GetAnimator()->ForceUpdate();
1151  pos += headEnt->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin();
1152  eyeOffset = pos + modelOffset;
1153  } else {
1154  // just base it off the bounding box size
1155  eyeOffset.z = GetPhysics()->GetBounds()[ 1 ].z - 6;
1156  }
1157  }
1158  headAnim.Init( this, headEnt->GetAnimator(), ANIMCHANNEL_ALL );
1159  } else {
1160  jointname = spawnArgs.GetString( "bone_leftEye" );
1161  leftEyeJoint = animator.GetJointHandle( jointname );
1162 
1163  jointname = spawnArgs.GetString( "bone_rightEye" );
1164  rightEyeJoint = animator.GetJointHandle( jointname );
1165 
1166  // set up the eye height. check if it's specified in the def.
1167  if ( !spawnArgs.GetFloat( "eye_height", "0", eyeOffset.z ) ) {
1168  // if not in the def, then try to base it off the idle animation
1169  int anim = animator.GetAnim( "idle" );
1170  if ( anim && ( leftEyeJoint != INVALID_JOINT ) ) {
1171  idVec3 pos;
1172  idMat3 axis;
1177  eyeOffset = pos + modelOffset;
1178  } else {
1179  // just base it off the bounding box size
1180  eyeOffset.z = GetPhysics()->GetBounds()[ 1 ].z - 6;
1181  }
1182  }
1184  }
1185 
1186  waitState = "";
1187 
1190 }
1191 
1192 /*
1193 =====================
1194 idActor::CheckBlink
1195 =====================
1196 */
1197 void idActor::CheckBlink( void ) {
1198  // check if it's time to blink
1199  if ( !blink_anim || ( health <= 0 ) || !allowEyeFocus || ( blink_time > gameLocal.time ) ) {
1200  return;
1201  }
1202 
1203  idEntity *headEnt = head.GetEntity();
1204  if ( headEnt ) {
1206  } else {
1208  }
1209 
1210  // set the next blink time
1212 }
1213 
1214 /*
1215 ================
1216 idActor::GetPhysicsToVisualTransform
1217 ================
1218 */
1220  if ( af.IsActive() ) {
1221  af.GetPhysicsToVisualTransform( origin, axis );
1222  return true;
1223  }
1224  origin = modelOffset;
1225  axis = viewAxis;
1226  return true;
1227 }
1228 
1229 /*
1230 ================
1231 idActor::GetPhysicsToSoundTransform
1232 ================
1233 */
1235  if ( soundJoint != INVALID_JOINT ) {
1237  origin += modelOffset;
1238  axis = viewAxis;
1239  } else {
1240  origin = GetPhysics()->GetGravityNormal() * -eyeOffset.z;
1241  axis.Identity();
1242  }
1243  return true;
1244 }
1245 
1246 /***********************************************************************
1247 
1248  script state management
1249 
1250 ***********************************************************************/
1251 
1252 /*
1253 ================
1254 idActor::ShutdownThreads
1255 ================
1256 */
1258  headAnim.Shutdown();
1259  torsoAnim.Shutdown();
1260  legsAnim.Shutdown();
1261 
1262  if ( scriptThread ) {
1265  delete scriptThread;
1266  scriptThread = NULL;
1267  }
1268 }
1269 
1270 /*
1271 ================
1272 idActor::ShouldConstructScriptObjectAtSpawn
1273 
1274 Called during idEntity::Spawn to see if it should construct the script object or not.
1275 Overridden by subclasses that need to spawn the script object themselves.
1276 ================
1277 */
1279  return false;
1280 }
1281 
1282 /*
1283 ================
1284 idActor::ConstructScriptObject
1285 
1286 Called during idEntity::Spawn. Calls the constructor on the script object.
1287 Can be overridden by subclasses when a thread doesn't need to be allocated.
1288 ================
1289 */
1291  const function_t *constructor;
1292 
1293  // make sure we have a scriptObject
1294  if ( !scriptObject.HasObject() ) {
1295  gameLocal.Error( "No scriptobject set on '%s'. Check the '%s' entityDef.", name.c_str(), GetEntityDefName() );
1296  }
1297 
1298  if ( !scriptThread ) {
1299  // create script thread
1300  scriptThread = new idThread();
1303  scriptThread->SetThreadName( name.c_str() );
1304  } else {
1306  }
1307 
1308  // call script object's constructor
1309  constructor = scriptObject.GetConstructor();
1310  if ( !constructor ) {
1311  gameLocal.Error( "Missing constructor on '%s' for entity '%s'", scriptObject.GetTypeName(), name.c_str() );
1312  }
1313 
1314  // init the script object's data
1316 
1317  // just set the current function on the script. we'll execute in the subclasses.
1318  scriptThread->CallFunction( this, constructor, true );
1319 
1320  return scriptThread;
1321 }
1322 
1323 /*
1324 =====================
1325 idActor::GetScriptFunction
1326 =====================
1327 */
1328 const function_t *idActor::GetScriptFunction( const char *funcname ) {
1329  const function_t *func;
1330 
1331  func = scriptObject.GetFunction( funcname );
1332  if ( !func ) {
1333  scriptThread->Error( "Unknown function '%s' in '%s'", funcname, scriptObject.GetTypeName() );
1334  }
1335 
1336  return func;
1337 }
1338 
1339 /*
1340 =====================
1341 idActor::SetState
1342 =====================
1343 */
1344 void idActor::SetState( const function_t *newState ) {
1345  if ( !newState ) {
1346  gameLocal.Error( "idActor::SetState: Null state" );
1347  }
1348 
1349  if ( ai_debugScript.GetInteger() == entityNumber ) {
1350  gameLocal.Printf( "%d: %s: State: %s\n", gameLocal.time, name.c_str(), newState->Name() );
1351  }
1352 
1353  state = newState;
1354  idealState = state;
1355  scriptThread->CallFunction( this, state, true );
1356 }
1357 
1358 /*
1359 =====================
1360 idActor::SetState
1361 =====================
1362 */
1363 void idActor::SetState( const char *statename ) {
1364  const function_t *newState;
1365 
1366  newState = GetScriptFunction( statename );
1367  SetState( newState );
1368 }
1369 
1370 /*
1371 =====================
1372 idActor::UpdateScript
1373 =====================
1374 */
1376  int i;
1377 
1378  if ( ai_debugScript.GetInteger() == entityNumber ) {
1380  } else {
1382  }
1383 
1384  // a series of state changes can happen in a single frame.
1385  // this loop limits them in case we've entered an infinite loop.
1386  for( i = 0; i < 20; i++ ) {
1387  if ( idealState != state ) {
1388  SetState( idealState );
1389  }
1390 
1391  // don't call script until it's done waiting
1392  if ( scriptThread->IsWaiting() ) {
1393  break;
1394  }
1395 
1396  scriptThread->Execute();
1397  if ( idealState == state ) {
1398  break;
1399  }
1400  }
1401 
1402  if ( i == 20 ) {
1403  scriptThread->Warning( "idActor::UpdateScript: exited loop to prevent lockup" );
1404  }
1405 }
1406 
1407 /***********************************************************************
1408 
1409  vision
1410 
1411 ***********************************************************************/
1412 
1413 /*
1414 =====================
1415 idActor::setFov
1416 =====================
1417 */
1418 void idActor::SetFOV( float fov ) {
1419  fovDot = (float)cos( DEG2RAD( fov * 0.5f ) );
1420 }
1421 
1422 /*
1423 =====================
1424 idActor::SetEyeHeight
1425 =====================
1426 */
1428  eyeOffset.z = height;
1429 }
1430 
1431 /*
1432 =====================
1433 idActor::EyeHeight
1434 =====================
1435 */
1436 float idActor::EyeHeight( void ) const {
1437  return eyeOffset.z;
1438 }
1439 
1440 /*
1441 =====================
1442 idActor::EyeOffset
1443 =====================
1444 */
1446  return GetPhysics()->GetGravityNormal() * -eyeOffset.z;
1447 }
1448 
1449 /*
1450 =====================
1451 idActor::GetEyePosition
1452 =====================
1453 */
1455  return GetPhysics()->GetOrigin() + ( GetPhysics()->GetGravityNormal() * -eyeOffset.z );
1456 }
1457 
1458 /*
1459 =====================
1460 idActor::GetViewPos
1461 =====================
1462 */
1463 void idActor::GetViewPos( idVec3 &origin, idMat3 &axis ) const {
1464  origin = GetEyePosition();
1465  axis = viewAxis;
1466 }
1467 
1468 /*
1469 =====================
1470 idActor::CheckFOV
1471 =====================
1472 */
1473 bool idActor::CheckFOV( const idVec3 &pos ) const {
1474  if ( fovDot == 1.0f ) {
1475  return true;
1476  }
1477 
1478  float dot;
1479  idVec3 delta;
1480 
1481  delta = pos - GetEyePosition();
1482 
1483  // get our gravity normal
1484  const idVec3 &gravityDir = GetPhysics()->GetGravityNormal();
1485 
1486  // infinite vertical vision, so project it onto our orientation plane
1487  delta -= gravityDir * ( gravityDir * delta );
1488 
1489  delta.Normalize();
1490  dot = viewAxis[ 0 ] * delta;
1491 
1492  return ( dot >= fovDot );
1493 }
1494 
1495 /*
1496 =====================
1497 idActor::CanSee
1498 =====================
1499 */
1500 bool idActor::CanSee( idEntity *ent, bool useFov ) const {
1501  trace_t tr;
1502  idVec3 eye;
1503  idVec3 toPos;
1504 
1505  if ( ent->IsHidden() ) {
1506  return false;
1507  }
1508 
1509  if ( ent->IsType( idActor::Type ) ) {
1510  toPos = ( ( idActor * )ent )->GetEyePosition();
1511  } else {
1512  toPos = ent->GetPhysics()->GetOrigin();
1513  }
1514 
1515  if ( useFov && !CheckFOV( toPos ) ) {
1516  return false;
1517  }
1518 
1519  eye = GetEyePosition();
1520 
1521  gameLocal.clip.TracePoint( tr, eye, toPos, MASK_OPAQUE, this );
1522  if ( tr.fraction >= 1.0f || ( gameLocal.GetTraceEntity( tr ) == ent ) ) {
1523  return true;
1524  }
1525 
1526  return false;
1527 }
1528 
1529 /*
1530 =====================
1531 idActor::PointVisible
1532 =====================
1533 */
1534 bool idActor::PointVisible( const idVec3 &point ) const {
1535  trace_t results;
1536  idVec3 start, end;
1537 
1538  start = GetEyePosition();
1539  end = point;
1540  end[2] += 1.0f;
1541 
1542  gameLocal.clip.TracePoint( results, start, end, MASK_OPAQUE, this );
1543  return ( results.fraction >= 1.0f );
1544 }
1545 
1546 /*
1547 =====================
1548 idActor::GetAIAimTargets
1549 
1550 Returns positions for the AI to aim at.
1551 =====================
1552 */
1553 void idActor::GetAIAimTargets( const idVec3 &lastSightPos, idVec3 &headPos, idVec3 &chestPos ) {
1554  headPos = lastSightPos + EyeOffset();
1555  chestPos = ( headPos + lastSightPos + GetPhysics()->GetBounds().GetCenter() ) * 0.5f;
1556 }
1557 
1558 /*
1559 =====================
1560 idActor::GetRenderView
1561 =====================
1562 */
1565  rv->viewaxis = viewAxis;
1566  rv->vieworg = GetEyePosition();
1567  return rv;
1568 }
1569 
1570 /***********************************************************************
1571 
1572  Model/Ragdoll
1573 
1574 ***********************************************************************/
1575 
1576 /*
1577 ================
1578 idActor::SetCombatModel
1579 ================
1580 */
1582  idAFAttachment *headEnt;
1583 
1584  if ( !use_combat_bbox ) {
1585  if ( combatModel ) {
1586  combatModel->Unlink();
1588  } else {
1590  }
1591 
1592  headEnt = head.GetEntity();
1593  if ( headEnt ) {
1594  headEnt->SetCombatModel();
1595  }
1596  }
1597 }
1598 
1599 /*
1600 ================
1601 idActor::GetCombatModel
1602 ================
1603 */
1605  return combatModel;
1606 }
1607 
1608 /*
1609 ================
1610 idActor::LinkCombat
1611 ================
1612 */
1613 void idActor::LinkCombat( void ) {
1614  idAFAttachment *headEnt;
1615 
1616  if ( fl.hidden || use_combat_bbox ) {
1617  return;
1618  }
1619 
1620  if ( combatModel ) {
1622  }
1623  headEnt = head.GetEntity();
1624  if ( headEnt ) {
1625  headEnt->LinkCombat();
1626  }
1627 }
1628 
1629 /*
1630 ================
1631 idActor::UnlinkCombat
1632 ================
1633 */
1635  idAFAttachment *headEnt;
1636 
1637  if ( combatModel ) {
1638  combatModel->Unlink();
1639  }
1640  headEnt = head.GetEntity();
1641  if ( headEnt ) {
1642  headEnt->UnlinkCombat();
1643  }
1644 }
1645 
1646 /*
1647 ================
1648 idActor::StartRagdoll
1649 ================
1650 */
1652  float slomoStart, slomoEnd;
1653  float jointFrictionDent, jointFrictionDentStart, jointFrictionDentEnd;
1654  float contactFrictionDent, contactFrictionDentStart, contactFrictionDentEnd;
1655 
1656  // if no AF loaded
1657  if ( !af.IsLoaded() ) {
1658  return false;
1659  }
1660 
1661  // if the AF is already active
1662  if ( af.IsActive() ) {
1663  return true;
1664  }
1665 
1666  // disable the monster bounding box
1667  GetPhysics()->DisableClip();
1668 
1669  // start using the AF
1670  af.StartFromCurrentPose( spawnArgs.GetInt( "velocityTime", "0" ) );
1671 
1672  slomoStart = MS2SEC( gameLocal.time ) + spawnArgs.GetFloat( "ragdoll_slomoStart", "-1.6" );
1673  slomoEnd = MS2SEC( gameLocal.time ) + spawnArgs.GetFloat( "ragdoll_slomoEnd", "0.8" );
1674 
1675  // do the first part of the death in slow motion
1676  af.GetPhysics()->SetTimeScaleRamp( slomoStart, slomoEnd );
1677 
1678  jointFrictionDent = spawnArgs.GetFloat( "ragdoll_jointFrictionDent", "0.1" );
1679  jointFrictionDentStart = MS2SEC( gameLocal.time ) + spawnArgs.GetFloat( "ragdoll_jointFrictionStart", "0.2" );
1680  jointFrictionDentEnd = MS2SEC( gameLocal.time ) + spawnArgs.GetFloat( "ragdoll_jointFrictionEnd", "1.2" );
1681 
1682  // set joint friction dent
1683  af.GetPhysics()->SetJointFrictionDent( jointFrictionDent, jointFrictionDentStart, jointFrictionDentEnd );
1684 
1685  contactFrictionDent = spawnArgs.GetFloat( "ragdoll_contactFrictionDent", "0.1" );
1686  contactFrictionDentStart = MS2SEC( gameLocal.time ) + spawnArgs.GetFloat( "ragdoll_contactFrictionStart", "1.0" );
1687  contactFrictionDentEnd = MS2SEC( gameLocal.time ) + spawnArgs.GetFloat( "ragdoll_contactFrictionEnd", "2.0" );
1688 
1689  // set contact friction dent
1690  af.GetPhysics()->SetContactFrictionDent( contactFrictionDent, contactFrictionDentStart, contactFrictionDentEnd );
1691 
1692  // drop any items the actor is holding
1693  idMoveableItem::DropItems( this, "death", NULL );
1694 
1695  // drop any articulated figures the actor is holding
1696  idAFEntity_Base::DropAFs( this, "death", NULL );
1697 
1699 
1700  return true;
1701 }
1702 
1703 /*
1704 ================
1705 idActor::StopRagdoll
1706 ================
1707 */
1708 void idActor::StopRagdoll( void ) {
1709  if ( af.IsActive() ) {
1710  af.Stop();
1711  }
1712 }
1713 
1714 /*
1715 ================
1716 idActor::UpdateAnimationControllers
1717 ================
1718 */
1720 
1721  if ( af.IsActive() ) {
1723  } else {
1725  }
1726 
1727  if ( walkIK.IsInitialized() ) {
1728  walkIK.Evaluate();
1729  return true;
1730  }
1731 
1732  return false;
1733 }
1734 
1735 /*
1736 ================
1737 idActor::RemoveAttachments
1738 ================
1739 */
1741  int i;
1742  idEntity *ent;
1743 
1744  // remove any attached entities
1745  for( i = 0; i < attachments.Num(); i++ ) {
1746  ent = attachments[ i ].ent.GetEntity();
1747  if ( ent && ent->spawnArgs.GetBool( "remove" ) ) {
1748  ent->PostEventMS( &EV_Remove, 0 );
1749  }
1750  }
1751 }
1752 
1753 /*
1754 ================
1755 idActor::Attach
1756 ================
1757 */
1759  idVec3 origin;
1760  idMat3 axis;
1761  jointHandle_t joint;
1762  idStr jointName;
1763  idAttachInfo &attach = attachments.Alloc();
1764  idAngles angleOffset;
1765  idVec3 originOffset;
1766 
1767  jointName = ent->spawnArgs.GetString( "joint" );
1768  joint = animator.GetJointHandle( jointName );
1769  if ( joint == INVALID_JOINT ) {
1770  gameLocal.Error( "Joint '%s' not found for attaching '%s' on '%s'", jointName.c_str(), ent->GetClassname(), name.c_str() );
1771  }
1772 
1773  angleOffset = ent->spawnArgs.GetAngles( "angles" );
1774  originOffset = ent->spawnArgs.GetVector( "origin" );
1775 
1776  attach.channel = animator.GetChannelForJoint( joint );
1777  GetJointWorldTransform( joint, gameLocal.time, origin, axis );
1778  attach.ent = ent;
1779 
1780  ent->SetOrigin( origin + originOffset * renderEntity.axis );
1781  idMat3 rotate = angleOffset.ToMat3();
1782  idMat3 newAxis = rotate * axis;
1783  ent->SetAxis( newAxis );
1784  ent->BindToJoint( this, joint, true );
1785  ent->cinematic = cinematic;
1786 }
1787 
1788 /*
1789 ================
1790 idActor::Teleport
1791 ================
1792 */
1793 void idActor::Teleport( const idVec3 &origin, const idAngles &angles, idEntity *destination ) {
1794  GetPhysics()->SetOrigin( origin + idVec3( 0, 0, CM_CLIP_EPSILON ) );
1796 
1797  viewAxis = angles.ToMat3();
1798 
1799  UpdateVisuals();
1800 
1801  if ( !IsHidden() ) {
1802  // kill anything at the new position
1803  gameLocal.KillBox( this );
1804  }
1805 }
1806 
1807 /*
1808 ================
1809 idActor::GetDeltaViewAngles
1810 ================
1811 */
1813  return deltaViewAngles;
1814 }
1815 
1816 /*
1817 ================
1818 idActor::SetDeltaViewAngles
1819 ================
1820 */
1822  deltaViewAngles = delta;
1823 }
1824 
1825 /*
1826 ================
1827 idActor::HasEnemies
1828 ================
1829 */
1830 bool idActor::HasEnemies( void ) const {
1831  idActor *ent;
1832 
1833  for( ent = enemyList.Next(); ent != NULL; ent = ent->enemyNode.Next() ) {
1834  if ( !ent->fl.hidden ) {
1835  return true;
1836  }
1837  }
1838 
1839  return false;
1840 }
1841 
1842 /*
1843 ================
1844 idActor::ClosestEnemyToPoint
1845 ================
1846 */
1848  idActor *ent;
1849  idActor *bestEnt;
1850  float bestDistSquared;
1851  float distSquared;
1852  idVec3 delta;
1853 
1854  bestDistSquared = idMath::INFINITY;
1855  bestEnt = NULL;
1856  for( ent = enemyList.Next(); ent != NULL; ent = ent->enemyNode.Next() ) {
1857  if ( ent->fl.hidden ) {
1858  continue;
1859  }
1860  delta = ent->GetPhysics()->GetOrigin() - pos;
1861  distSquared = delta.LengthSqr();
1862  if ( distSquared < bestDistSquared ) {
1863  bestEnt = ent;
1864  bestDistSquared = distSquared;
1865  }
1866  }
1867 
1868  return bestEnt;
1869 }
1870 
1871 /*
1872 ================
1873 idActor::EnemyWithMostHealth
1874 ================
1875 */
1877  idActor *ent;
1878  idActor *bestEnt;
1879 
1880  int most = -9999;
1881  bestEnt = NULL;
1882  for( ent = enemyList.Next(); ent != NULL; ent = ent->enemyNode.Next() ) {
1883  if ( !ent->fl.hidden && ( ent->health > most ) ) {
1884  bestEnt = ent;
1885  most = ent->health;
1886  }
1887  }
1888  return bestEnt;
1889 }
1890 
1891 /*
1892 ================
1893 idActor::OnLadder
1894 ================
1895 */
1896 bool idActor::OnLadder( void ) const {
1897  return false;
1898 }
1899 
1900 /*
1901 ==============
1902 idActor::GetAASLocation
1903 ==============
1904 */
1905 void idActor::GetAASLocation( idAAS *aas, idVec3 &pos, int &areaNum ) const {
1906  idVec3 size;
1907  idBounds bounds;
1908 
1909  GetFloorPos( 64.0f, pos );
1910  if ( !aas ) {
1911  areaNum = 0;
1912  return;
1913  }
1914 
1915  size = aas->GetSettings()->boundingBoxes[0][1];
1916  bounds[0] = -size;
1917  size.z = 32.0f;
1918  bounds[1] = size;
1919 
1920  areaNum = aas->PointReachableAreaNum( pos, bounds, AREA_REACHABLE_WALK );
1921  if ( areaNum ) {
1922  aas->PushPointIntoAreaNum( areaNum, pos );
1923  }
1924 }
1925 
1926 /***********************************************************************
1927 
1928  animation state
1929 
1930 ***********************************************************************/
1931 
1932 /*
1933 =====================
1934 idActor::SetAnimState
1935 =====================
1936 */
1937 void idActor::SetAnimState( int channel, const char *statename, int blendFrames ) {
1938  const function_t *func;
1939 
1940  func = scriptObject.GetFunction( statename );
1941  if ( !func ) {
1942  assert( 0 );
1943  gameLocal.Error( "Can't find function '%s' in object '%s'", statename, scriptObject.GetTypeName() );
1944  }
1945 
1946  switch( channel ) {
1947  case ANIMCHANNEL_HEAD :
1948  headAnim.SetState( statename, blendFrames );
1949  allowEyeFocus = true;
1950  break;
1951 
1952  case ANIMCHANNEL_TORSO :
1953  torsoAnim.SetState( statename, blendFrames );
1954  legsAnim.Enable( blendFrames );
1955  allowPain = true;
1956  allowEyeFocus = true;
1957  break;
1958 
1959  case ANIMCHANNEL_LEGS :
1960  legsAnim.SetState( statename, blendFrames );
1961  torsoAnim.Enable( blendFrames );
1962  allowPain = true;
1963  allowEyeFocus = true;
1964  break;
1965 
1966  default:
1967  gameLocal.Error( "idActor::SetAnimState: Unknown anim group" );
1968  break;
1969  }
1970 }
1971 
1972 /*
1973 =====================
1974 idActor::GetAnimState
1975 =====================
1976 */
1977 const char *idActor::GetAnimState( int channel ) const {
1978  switch( channel ) {
1979  case ANIMCHANNEL_HEAD :
1980  return headAnim.state;
1981  break;
1982 
1983  case ANIMCHANNEL_TORSO :
1984  return torsoAnim.state;
1985  break;
1986 
1987  case ANIMCHANNEL_LEGS :
1988  return legsAnim.state;
1989  break;
1990 
1991  default:
1992  gameLocal.Error( "idActor::GetAnimState: Unknown anim group" );
1993  return NULL;
1994  break;
1995  }
1996 }
1997 
1998 /*
1999 =====================
2000 idActor::InAnimState
2001 =====================
2002 */
2003 bool idActor::InAnimState( int channel, const char *statename ) const {
2004  switch( channel ) {
2005  case ANIMCHANNEL_HEAD :
2006  if ( headAnim.state == statename ) {
2007  return true;
2008  }
2009  break;
2010 
2011  case ANIMCHANNEL_TORSO :
2012  if ( torsoAnim.state == statename ) {
2013  return true;
2014  }
2015  break;
2016 
2017  case ANIMCHANNEL_LEGS :
2018  if ( legsAnim.state == statename ) {
2019  return true;
2020  }
2021  break;
2022 
2023  default:
2024  gameLocal.Error( "idActor::InAnimState: Unknown anim group" );
2025  break;
2026  }
2027 
2028  return false;
2029 }
2030 
2031 /*
2032 =====================
2033 idActor::WaitState
2034 =====================
2035 */
2036 const char *idActor::WaitState( void ) const {
2037  if ( waitState.Length() ) {
2038  return waitState;
2039  } else {
2040  return NULL;
2041  }
2042 }
2043 
2044 /*
2045 =====================
2046 idActor::SetWaitState
2047 =====================
2048 */
2049 void idActor::SetWaitState( const char *_waitstate ) {
2050  waitState = _waitstate;
2051 }
2052 
2053 /*
2054 =====================
2055 idActor::UpdateAnimState
2056 =====================
2057 */
2062 }
2063 
2064 /*
2065 =====================
2066 idActor::GetAnim
2067 =====================
2068 */
2069 int idActor::GetAnim( int channel, const char *animname ) {
2070  int anim;
2071  const char *temp;
2072  idAnimator *animatorPtr;
2073 
2074  if ( channel == ANIMCHANNEL_HEAD ) {
2075  if ( !head.GetEntity() ) {
2076  return 0;
2077  }
2078  animatorPtr = head.GetEntity()->GetAnimator();
2079  } else {
2080  animatorPtr = &animator;
2081  }
2082 
2083  if ( animPrefix.Length() ) {
2084  temp = va( "%s_%s", animPrefix.c_str(), animname );
2085  anim = animatorPtr->GetAnim( temp );
2086  if ( anim ) {
2087  return anim;
2088  }
2089  }
2090 
2091  anim = animatorPtr->GetAnim( animname );
2092 
2093  return anim;
2094 }
2095 
2096 /*
2097 ===============
2098 idActor::SyncAnimChannels
2099 ===============
2100 */
2101 void idActor::SyncAnimChannels( int channel, int syncToChannel, int blendFrames ) {
2102  idAnimator *headAnimator;
2103  idAFAttachment *headEnt;
2104  int anim;
2105  idAnimBlend *syncAnim;
2106  int starttime;
2107  int blendTime;
2108  int cycle;
2109 
2110  blendTime = FRAME2MS( blendFrames );
2111  if ( channel == ANIMCHANNEL_HEAD ) {
2112  headEnt = head.GetEntity();
2113  if ( headEnt ) {
2114  headAnimator = headEnt->GetAnimator();
2115  syncAnim = animator.CurrentAnim( syncToChannel );
2116  if ( syncAnim ) {
2117  anim = headAnimator->GetAnim( syncAnim->AnimFullName() );
2118  if ( !anim ) {
2119  anim = headAnimator->GetAnim( syncAnim->AnimName() );
2120  }
2121  if ( anim ) {
2122  cycle = animator.CurrentAnim( syncToChannel )->GetCycleCount();
2123  starttime = animator.CurrentAnim( syncToChannel )->GetStartTime();
2124  headAnimator->PlayAnim( ANIMCHANNEL_ALL, anim, gameLocal.time, blendTime );
2125  headAnimator->CurrentAnim( ANIMCHANNEL_ALL )->SetCycleCount( cycle );
2126  headAnimator->CurrentAnim( ANIMCHANNEL_ALL )->SetStartTime( starttime );
2127  } else {
2128  headEnt->PlayIdleAnim( blendTime );
2129  }
2130  }
2131  }
2132  } else if ( syncToChannel == ANIMCHANNEL_HEAD ) {
2133  headEnt = head.GetEntity();
2134  if ( headEnt ) {
2135  headAnimator = headEnt->GetAnimator();
2136  syncAnim = headAnimator->CurrentAnim( ANIMCHANNEL_ALL );
2137  if ( syncAnim ) {
2138  anim = GetAnim( channel, syncAnim->AnimFullName() );
2139  if ( !anim ) {
2140  anim = GetAnim( channel, syncAnim->AnimName() );
2141  }
2142  if ( anim ) {
2143  cycle = headAnimator->CurrentAnim( ANIMCHANNEL_ALL )->GetCycleCount();
2144  starttime = headAnimator->CurrentAnim( ANIMCHANNEL_ALL )->GetStartTime();
2145  animator.PlayAnim( channel, anim, gameLocal.time, blendTime );
2146  animator.CurrentAnim( channel )->SetCycleCount( cycle );
2147  animator.CurrentAnim( channel )->SetStartTime( starttime );
2148  }
2149  }
2150  }
2151  } else {
2152  animator.SyncAnimChannels( channel, syncToChannel, gameLocal.time, blendTime );
2153  }
2154 }
2155 
2156 /***********************************************************************
2157 
2158  Damage
2159 
2160 ***********************************************************************/
2161 
2162 /*
2163 ============
2164 idActor::Gib
2165 ============
2166 */
2167 void idActor::Gib( const idVec3 &dir, const char *damageDefName ) {
2168  // no gibbing in multiplayer - by self damage or by moving objects
2169  if ( gameLocal.isMultiplayer ) {
2170  return;
2171  }
2172  // only gib once
2173  if ( gibbed ) {
2174  return;
2175  }
2176  idAFEntity_Gibbable::Gib( dir, damageDefName );
2177  if ( head.GetEntity() ) {
2178  head.GetEntity()->Hide();
2179  }
2180  StopSound( SND_CHANNEL_VOICE, false );
2181 }
2182 
2183 
2184 /*
2185 ============
2186 idActor::Damage
2187 
2188 this entity that is being damaged
2189 inflictor entity that is causing the damage
2190 attacker entity that caused the inflictor to damage targ
2191  example: this=monster, inflictor=rocket, attacker=player
2192 
2193 dir direction of the attack for knockback in global space
2194 point point at which the damage is being inflicted, used for headshots
2195 damage amount of damage being inflicted
2196 
2197 inflictor, attacker, dir, and point can be NULL for environmental effects
2198 
2199 Bleeding wounds and surface overlays are applied in the collision code that
2200 calls Damage()
2201 ============
2202 */
2203 void idActor::Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir,
2204  const char *damageDefName, const float damageScale, const int location ) {
2205  if ( !fl.takedamage ) {
2206  return;
2207  }
2208 
2209  if ( !inflictor ) {
2210  inflictor = gameLocal.world;
2211  }
2212  if ( !attacker ) {
2213  attacker = gameLocal.world;
2214  }
2215 
2216 #ifdef _D3XP
2217  SetTimeState ts( timeGroup );
2218 
2219  // Helltime boss is immune to all projectiles except the helltime killer
2220  if ( finalBoss && idStr::Icmp(inflictor->GetEntityDefName(), "projectile_helltime_killer") ) {
2221  return;
2222  }
2223 
2224  // Maledict is immume to the falling asteroids
2225  if ( !idStr::Icmp( GetEntityDefName(), "monster_boss_d3xp_maledict" ) &&
2226  (!idStr::Icmp( damageDefName, "damage_maledict_asteroid" ) || !idStr::Icmp( damageDefName, "damage_maledict_asteroid_splash" ) ) ) {
2227  return;
2228  }
2229 #else
2230  if ( finalBoss && !inflictor->IsType( idSoulCubeMissile::Type ) ) {
2231  return;
2232  }
2233 #endif
2234 
2235  const idDict *damageDef = gameLocal.FindEntityDefDict( damageDefName );
2236  if ( !damageDef ) {
2237  gameLocal.Error( "Unknown damageDef '%s'", damageDefName );
2238  }
2239 
2240  int damage = damageDef->GetInt( "damage" ) * damageScale;
2241  damage = GetDamageForLocation( damage, location );
2242 
2243  // inform the attacker that they hit someone
2244  attacker->DamageFeedback( this, inflictor, damage );
2245  if ( damage > 0 ) {
2246  health -= damage;
2247 
2248 #ifdef _D3XP
2249  //Check the health against any damage cap that is currently set
2250  if(damageCap >= 0 && health < damageCap) {
2251  health = damageCap;
2252  }
2253 #endif
2254 
2255  if ( health <= 0 ) {
2256  if ( health < -999 ) {
2257  health = -999;
2258  }
2259  Killed( inflictor, attacker, damage, dir, location );
2260  if ( ( health < -20 ) && spawnArgs.GetBool( "gib" ) && damageDef->GetBool( "gib" ) ) {
2261  Gib( dir, damageDefName );
2262  }
2263  } else {
2264  Pain( inflictor, attacker, damage, dir, location );
2265  }
2266  } else {
2267  // don't accumulate knockback
2268  if ( af.IsLoaded() ) {
2269  // clear impacts
2270  af.Rest();
2271 
2272  // physics is turned off by calling af.Rest()
2274  }
2275  }
2276 }
2277 
2278 /*
2279 =====================
2280 idActor::ClearPain
2281 =====================
2282 */
2283 void idActor::ClearPain( void ) {
2284  pain_debounce_time = 0;
2285 }
2286 
2287 /*
2288 =====================
2289 idActor::Pain
2290 =====================
2291 */
2292 bool idActor::Pain( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ) {
2293  if ( af.IsLoaded() ) {
2294  // clear impacts
2295  af.Rest();
2296 
2297  // physics is turned off by calling af.Rest()
2299  }
2300 
2301  if ( gameLocal.time < pain_debounce_time ) {
2302  return false;
2303  }
2304 
2305  // don't play pain sounds more than necessary
2307 
2308  if ( health > 75 ) {
2309  StartSound( "snd_pain_small", SND_CHANNEL_VOICE, 0, false, NULL );
2310  } else if ( health > 50 ) {
2311  StartSound( "snd_pain_medium", SND_CHANNEL_VOICE, 0, false, NULL );
2312  } else if ( health > 25 ) {
2313  StartSound( "snd_pain_large", SND_CHANNEL_VOICE, 0, false, NULL );
2314  } else {
2315  StartSound( "snd_pain_huge", SND_CHANNEL_VOICE, 0, false, NULL );
2316  }
2317 
2318  if ( !allowPain || ( gameLocal.time < painTime ) ) {
2319  // don't play a pain anim
2320  return false;
2321  }
2322 
2323  if ( pain_threshold && ( damage < pain_threshold ) ) {
2324  return false;
2325  }
2326 
2327  // set the pain anim
2328  idStr damageGroup = GetDamageGroup( location );
2329 
2330  painAnim = "";
2331  if ( animPrefix.Length() ) {
2332  if ( damageGroup.Length() && ( damageGroup != "legs" ) ) {
2333  sprintf( painAnim, "%s_pain_%s", animPrefix.c_str(), damageGroup.c_str() );
2334  if ( !animator.HasAnim( painAnim ) ) {
2335  sprintf( painAnim, "pain_%s", damageGroup.c_str() );
2336  if ( !animator.HasAnim( painAnim ) ) {
2337  painAnim = "";
2338  }
2339  }
2340  }
2341 
2342  if ( !painAnim.Length() ) {
2343  sprintf( painAnim, "%s_pain", animPrefix.c_str() );
2344  if ( !animator.HasAnim( painAnim ) ) {
2345  painAnim = "";
2346  }
2347  }
2348  } else if ( damageGroup.Length() && ( damageGroup != "legs" ) ) {
2349  sprintf( painAnim, "pain_%s", damageGroup.c_str() );
2350  if ( !animator.HasAnim( painAnim ) ) {
2351  sprintf( painAnim, "pain_%s", damageGroup.c_str() );
2352  if ( !animator.HasAnim( painAnim ) ) {
2353  painAnim = "";
2354  }
2355  }
2356  }
2357 
2358  if ( !painAnim.Length() ) {
2359  painAnim = "pain";
2360  }
2361 
2362  if ( g_debugDamage.GetBool() ) {
2363  gameLocal.Printf( "Damage: joint: '%s', zone '%s', anim '%s'\n", animator.GetJointName( ( jointHandle_t )location ),
2364  damageGroup.c_str(), painAnim.c_str() );
2365  }
2366 
2367  return true;
2368 }
2369 
2370 /*
2371 =====================
2372 idActor::SpawnGibs
2373 =====================
2374 */
2375 void idActor::SpawnGibs( const idVec3 &dir, const char *damageDefName ) {
2376  idAFEntity_Gibbable::SpawnGibs( dir, damageDefName );
2378 }
2379 
2380 /*
2381 =====================
2382 idActor::SetupDamageGroups
2383 
2384 FIXME: only store group names once and store an index for each joint
2385 =====================
2386 */
2388  int i;
2389  const idKeyValue *arg;
2390  idStr groupname;
2391  idList<jointHandle_t> jointList;
2392  int jointnum;
2393  float scale;
2394 
2395  // create damage zones
2397  arg = spawnArgs.MatchPrefix( "damage_zone ", NULL );
2398  while ( arg ) {
2399  groupname = arg->GetKey();
2400  groupname.Strip( "damage_zone " );
2401  animator.GetJointList( arg->GetValue(), jointList );
2402  for( i = 0; i < jointList.Num(); i++ ) {
2403  jointnum = jointList[ i ];
2404  damageGroups[ jointnum ] = groupname;
2405  }
2406  jointList.Clear();
2407  arg = spawnArgs.MatchPrefix( "damage_zone ", arg );
2408  }
2409 
2410  // initilize the damage zones to normal damage
2412  for( i = 0; i < damageScale.Num(); i++ ) {
2413  damageScale[ i ] = 1.0f;
2414  }
2415 
2416  // set the percentage on damage zones
2417  arg = spawnArgs.MatchPrefix( "damage_scale ", NULL );
2418  while ( arg ) {
2419  scale = atof( arg->GetValue() );
2420  groupname = arg->GetKey();
2421  groupname.Strip( "damage_scale " );
2422  for( i = 0; i < damageScale.Num(); i++ ) {
2423  if ( damageGroups[ i ] == groupname ) {
2424  damageScale[ i ] = scale;
2425  }
2426  }
2427  arg = spawnArgs.MatchPrefix( "damage_scale ", arg );
2428  }
2429 }
2430 
2431 /*
2432 =====================
2433 idActor::GetDamageForLocation
2434 =====================
2435 */
2436 int idActor::GetDamageForLocation( int damage, int location ) {
2437  if ( ( location < 0 ) || ( location >= damageScale.Num() ) ) {
2438  return damage;
2439  }
2440 
2441  return (int)ceil( damage * damageScale[ location ] );
2442 }
2443 
2444 /*
2445 =====================
2446 idActor::GetDamageGroup
2447 =====================
2448 */
2449 const char *idActor::GetDamageGroup( int location ) {
2450  if ( ( location < 0 ) || ( location >= damageGroups.Num() ) ) {
2451  return "";
2452  }
2453 
2454  return damageGroups[ location ];
2455 }
2456 
2457 
2458 /***********************************************************************
2459 
2460  Events
2461 
2462 ***********************************************************************/
2463 
2464 /*
2465 =====================
2466 idActor::Event_EnableEyeFocus
2467 =====================
2468 */
2470  const char *sound = NULL;
2471  const idMaterial *material;
2472 
2473  if ( !GetPhysics()->HasGroundContacts() ) {
2474  return;
2475  }
2476 
2477  // start footstep sound based on material type
2478  material = GetPhysics()->GetContact( 0 ).material;
2479  if ( material != NULL ) {
2480  sound = spawnArgs.GetString( va( "snd_footstep_%s", gameLocal.sufaceTypeNames[ material->GetSurfaceType() ] ) );
2481  }
2482  if ( *sound == '\0' ) {
2483  sound = spawnArgs.GetString( "snd_footstep" );
2484  }
2485  if ( *sound != '\0' ) {
2486  StartSoundShader( declManager->FindSound( sound ), SND_CHANNEL_BODY, 0, false, NULL );
2487  }
2488 }
2489 
2490 /*
2491 =====================
2492 idActor::Event_EnableEyeFocus
2493 =====================
2494 */
2496  allowEyeFocus = true;
2498 }
2499 
2500 /*
2501 =====================
2502 idActor::Event_DisableEyeFocus
2503 =====================
2504 */
2506  allowEyeFocus = false;
2507 
2508  idEntity *headEnt = head.GetEntity();
2509  if ( headEnt ) {
2511  } else {
2513  }
2514 }
2515 
2516 /*
2517 ===============
2518 idActor::Event_Footstep
2519 ===============
2520 */
2523 }
2524 
2525 /*
2526 =====================
2527 idActor::Event_EnableWalkIK
2528 =====================
2529 */
2531  walkIK.EnableAll();
2532 }
2533 
2534 /*
2535 =====================
2536 idActor::Event_DisableWalkIK
2537 =====================
2538 */
2540  walkIK.DisableAll();
2541 }
2542 
2543 /*
2544 =====================
2545 idActor::Event_EnableLegIK
2546 =====================
2547 */
2549  walkIK.EnableLeg( num );
2550 }
2551 
2552 /*
2553 =====================
2554 idActor::Event_DisableLegIK
2555 =====================
2556 */
2558  walkIK.DisableLeg( num );
2559 }
2560 
2561 /*
2562 =====================
2563 idActor::Event_PreventPain
2564 =====================
2565 */
2566 void idActor::Event_PreventPain( float duration ) {
2567  painTime = gameLocal.time + SEC2MS( duration );
2568 }
2569 
2570 /*
2571 ===============
2572 idActor::Event_DisablePain
2573 ===============
2574 */
2576  allowPain = false;
2577 }
2578 
2579 /*
2580 ===============
2581 idActor::Event_EnablePain
2582 ===============
2583 */
2585  allowPain = true;
2586 }
2587 
2588 /*
2589 =====================
2590 idActor::Event_GetPainAnim
2591 =====================
2592 */
2594  if ( !painAnim.Length() ) {
2595  idThread::ReturnString( "pain" );
2596  } else {
2598  }
2599 }
2600 
2601 /*
2602 =====================
2603 idActor::Event_SetAnimPrefix
2604 =====================
2605 */
2606 void idActor::Event_SetAnimPrefix( const char *prefix ) {
2607  animPrefix = prefix;
2608 }
2609 
2610 /*
2611 ===============
2612 idActor::Event_StopAnim
2613 ===============
2614 */
2615 void idActor::Event_StopAnim( int channel, int frames ) {
2616  switch( channel ) {
2617  case ANIMCHANNEL_HEAD :
2618  headAnim.StopAnim( frames );
2619  break;
2620 
2621  case ANIMCHANNEL_TORSO :
2622  torsoAnim.StopAnim( frames );
2623  break;
2624 
2625  case ANIMCHANNEL_LEGS :
2626  legsAnim.StopAnim( frames );
2627  break;
2628 
2629  default:
2630  gameLocal.Error( "Unknown anim group" );
2631  break;
2632  }
2633 }
2634 
2635 /*
2636 ===============
2637 idActor::Event_PlayAnim
2638 ===============
2639 */
2640 void idActor::Event_PlayAnim( int channel, const char *animname ) {
2641  animFlags_t flags;
2642  idEntity *headEnt;
2643  int anim;
2644 
2645  anim = GetAnim( channel, animname );
2646  if ( !anim ) {
2647  if ( ( channel == ANIMCHANNEL_HEAD ) && head.GetEntity() ) {
2648  gameLocal.DPrintf( "missing '%s' animation on '%s' (%s)\n", animname, name.c_str(), spawnArgs.GetString( "def_head", "" ) );
2649  } else {
2650  gameLocal.DPrintf( "missing '%s' animation on '%s' (%s)\n", animname, name.c_str(), GetEntityDefName() );
2651  }
2652  idThread::ReturnInt( 0 );
2653  return;
2654  }
2655 
2656  switch( channel ) {
2657  case ANIMCHANNEL_HEAD :
2658  headEnt = head.GetEntity();
2659  if ( headEnt ) {
2660  headAnim.idleAnim = false;
2661  headAnim.PlayAnim( anim );
2662  flags = headAnim.GetAnimFlags();
2663  if ( !flags.prevent_idle_override ) {
2664  if ( torsoAnim.IsIdle() ) {
2667  if ( legsAnim.IsIdle() ) {
2670  }
2671  }
2672  }
2673  }
2674  break;
2675 
2676  case ANIMCHANNEL_TORSO :
2677  torsoAnim.idleAnim = false;
2678  torsoAnim.PlayAnim( anim );
2679  flags = torsoAnim.GetAnimFlags();
2680  if ( !flags.prevent_idle_override ) {
2681  if ( headAnim.IsIdle() ) {
2684  }
2685  if ( legsAnim.IsIdle() ) {
2688  }
2689  }
2690  break;
2691 
2692  case ANIMCHANNEL_LEGS :
2693  legsAnim.idleAnim = false;
2694  legsAnim.PlayAnim( anim );
2695  flags = legsAnim.GetAnimFlags();
2696  if ( !flags.prevent_idle_override ) {
2697  if ( torsoAnim.IsIdle() ) {
2700  if ( headAnim.IsIdle() ) {
2703  }
2704  }
2705  }
2706  break;
2707 
2708  default :
2709  gameLocal.Error( "Unknown anim group" );
2710  break;
2711  }
2712  idThread::ReturnInt( 1 );
2713 }
2714 
2715 /*
2716 ===============
2717 idActor::Event_PlayCycle
2718 ===============
2719 */
2720 void idActor::Event_PlayCycle( int channel, const char *animname ) {
2721  animFlags_t flags;
2722  int anim;
2723 
2724  anim = GetAnim( channel, animname );
2725  if ( !anim ) {
2726  if ( ( channel == ANIMCHANNEL_HEAD ) && head.GetEntity() ) {
2727  gameLocal.DPrintf( "missing '%s' animation on '%s' (%s)\n", animname, name.c_str(), spawnArgs.GetString( "def_head", "" ) );
2728  } else {
2729  gameLocal.DPrintf( "missing '%s' animation on '%s' (%s)\n", animname, name.c_str(), GetEntityDefName() );
2730  }
2731  idThread::ReturnInt( false );
2732  return;
2733  }
2734 
2735  switch( channel ) {
2736  case ANIMCHANNEL_HEAD :
2737  headAnim.idleAnim = false;
2738  headAnim.CycleAnim( anim );
2739  flags = headAnim.GetAnimFlags();
2740  if ( !flags.prevent_idle_override ) {
2741  if ( torsoAnim.IsIdle() && legsAnim.IsIdle() ) {
2746  }
2747  }
2748  break;
2749 
2750  case ANIMCHANNEL_TORSO :
2751  torsoAnim.idleAnim = false;
2752  torsoAnim.CycleAnim( anim );
2753  flags = torsoAnim.GetAnimFlags();
2754  if ( !flags.prevent_idle_override ) {
2755  if ( headAnim.IsIdle() ) {
2758  }
2759  if ( legsAnim.IsIdle() ) {
2762  }
2763  }
2764  break;
2765 
2766  case ANIMCHANNEL_LEGS :
2767  legsAnim.idleAnim = false;
2768  legsAnim.CycleAnim( anim );
2769  flags = legsAnim.GetAnimFlags();
2770  if ( !flags.prevent_idle_override ) {
2771  if ( torsoAnim.IsIdle() ) {
2774  if ( headAnim.IsIdle() ) {
2777  }
2778  }
2779  }
2780  break;
2781 
2782  default:
2783  gameLocal.Error( "Unknown anim group" );
2784  }
2785 
2786  idThread::ReturnInt( true );
2787 }
2788 
2789 /*
2790 ===============
2791 idActor::Event_IdleAnim
2792 ===============
2793 */
2794 void idActor::Event_IdleAnim( int channel, const char *animname ) {
2795  int anim;
2796 
2797  anim = GetAnim( channel, animname );
2798  if ( !anim ) {
2799  if ( ( channel == ANIMCHANNEL_HEAD ) && head.GetEntity() ) {
2800  gameLocal.DPrintf( "missing '%s' animation on '%s' (%s)\n", animname, name.c_str(), spawnArgs.GetString( "def_head", "" ) );
2801  } else {
2802  gameLocal.DPrintf( "missing '%s' animation on '%s' (%s)\n", animname, name.c_str(), GetEntityDefName() );
2803  }
2804 
2805  switch( channel ) {
2806  case ANIMCHANNEL_HEAD :
2807  headAnim.BecomeIdle();
2808  break;
2809 
2810  case ANIMCHANNEL_TORSO :
2812  break;
2813 
2814  case ANIMCHANNEL_LEGS :
2815  legsAnim.BecomeIdle();
2816  break;
2817 
2818  default:
2819  gameLocal.Error( "Unknown anim group" );
2820  }
2821 
2822  idThread::ReturnInt( false );
2823  return;
2824  }
2825 
2826  switch( channel ) {
2827  case ANIMCHANNEL_HEAD :
2828  headAnim.BecomeIdle();
2830  // don't sync to torso body if it doesn't override idle anims
2831  headAnim.CycleAnim( anim );
2832  } else if ( torsoAnim.IsIdle() && legsAnim.IsIdle() ) {
2833  // everything is idle, so play the anim on the head and copy it to the torso and legs
2834  headAnim.CycleAnim( anim );
2839  } else if ( torsoAnim.IsIdle() ) {
2840  // sync the head and torso to the legs
2844  } else {
2845  // sync the head to the torso
2847  }
2848  break;
2849 
2850  case ANIMCHANNEL_TORSO :
2853  // don't sync to legs if legs anim doesn't override idle anims
2854  torsoAnim.CycleAnim( anim );
2855  } else if ( legsAnim.IsIdle() ) {
2856  // play the anim in both legs and torso
2857  torsoAnim.CycleAnim( anim );
2860  } else {
2861  // sync the anim to the legs
2863  }
2864 
2865  if ( headAnim.IsIdle() ) {
2867  }
2868  break;
2869 
2870  case ANIMCHANNEL_LEGS :
2871  legsAnim.BecomeIdle();
2873  // don't sync to torso if torso anim doesn't override idle anims
2874  legsAnim.CycleAnim( anim );
2875  } else if ( torsoAnim.IsIdle() ) {
2876  // play the anim in both legs and torso
2877  legsAnim.CycleAnim( anim );
2880  if ( headAnim.IsIdle() ) {
2882  }
2883  } else {
2884  // sync the anim to the torso
2886  }
2887  break;
2888 
2889  default:
2890  gameLocal.Error( "Unknown anim group" );
2891  }
2892 
2893  idThread::ReturnInt( true );
2894 }
2895 
2896 /*
2897 ================
2898 idActor::Event_SetSyncedAnimWeight
2899 ================
2900 */
2901 void idActor::Event_SetSyncedAnimWeight( int channel, int anim, float weight ) {
2902  idEntity *headEnt;
2903 
2904  headEnt = head.GetEntity();
2905  switch( channel ) {
2906  case ANIMCHANNEL_HEAD :
2907  if ( headEnt ) {
2909  } else {
2911  }
2912  if ( torsoAnim.IsIdle() ) {
2914  if ( legsAnim.IsIdle() ) {
2916  }
2917  }
2918  break;
2919 
2920  case ANIMCHANNEL_TORSO :
2922  if ( legsAnim.IsIdle() ) {
2924  }
2925  if ( headEnt && headAnim.IsIdle() ) {
2927  }
2928  break;
2929 
2930  case ANIMCHANNEL_LEGS :
2932  if ( torsoAnim.IsIdle() ) {
2934  if ( headEnt && headAnim.IsIdle() ) {
2936  }
2937  }
2938  break;
2939 
2940  default:
2941  gameLocal.Error( "Unknown anim group" );
2942  }
2943 }
2944 
2945 /*
2946 ===============
2947 idActor::Event_OverrideAnim
2948 ===============
2949 */
2950 void idActor::Event_OverrideAnim( int channel ) {
2951  switch( channel ) {
2952  case ANIMCHANNEL_HEAD :
2953  headAnim.Disable();
2954  if ( !torsoAnim.IsIdle() ) {
2956  } else {
2958  }
2959  break;
2960 
2961  case ANIMCHANNEL_TORSO :
2962  torsoAnim.Disable();
2964  if ( headAnim.IsIdle() ) {
2966  }
2967  break;
2968 
2969  case ANIMCHANNEL_LEGS :
2970  legsAnim.Disable();
2972  break;
2973 
2974  default:
2975  gameLocal.Error( "Unknown anim group" );
2976  break;
2977  }
2978 }
2979 
2980 /*
2981 ===============
2982 idActor::Event_EnableAnim
2983 ===============
2984 */
2985 void idActor::Event_EnableAnim( int channel, int blendFrames ) {
2986  switch( channel ) {
2987  case ANIMCHANNEL_HEAD :
2988  headAnim.Enable( blendFrames );
2989  break;
2990 
2991  case ANIMCHANNEL_TORSO :
2992  torsoAnim.Enable( blendFrames );
2993  break;
2994 
2995  case ANIMCHANNEL_LEGS :
2996  legsAnim.Enable( blendFrames );
2997  break;
2998 
2999  default:
3000  gameLocal.Error( "Unknown anim group" );
3001  break;
3002  }
3003 }
3004 
3005 /*
3006 ===============
3007 idActor::Event_SetBlendFrames
3008 ===============
3009 */
3010 void idActor::Event_SetBlendFrames( int channel, int blendFrames ) {
3011  switch( channel ) {
3012  case ANIMCHANNEL_HEAD :
3013  headAnim.animBlendFrames = blendFrames;
3014  headAnim.lastAnimBlendFrames = blendFrames;
3015  break;
3016 
3017  case ANIMCHANNEL_TORSO :
3018  torsoAnim.animBlendFrames = blendFrames;
3019  torsoAnim.lastAnimBlendFrames = blendFrames;
3020  break;
3021 
3022  case ANIMCHANNEL_LEGS :
3023  legsAnim.animBlendFrames = blendFrames;
3024  legsAnim.lastAnimBlendFrames = blendFrames;
3025  break;
3026 
3027  default:
3028  gameLocal.Error( "Unknown anim group" );
3029  break;
3030  }
3031 }
3032 
3033 /*
3034 ===============
3035 idActor::Event_GetBlendFrames
3036 ===============
3037 */
3038 void idActor::Event_GetBlendFrames( int channel ) {
3039  switch( channel ) {
3040  case ANIMCHANNEL_HEAD :
3042  break;
3043 
3044  case ANIMCHANNEL_TORSO :
3046  break;
3047 
3048  case ANIMCHANNEL_LEGS :
3050  break;
3051 
3052  default:
3053  gameLocal.Error( "Unknown anim group" );
3054  break;
3055  }
3056 }
3057 
3058 /*
3059 ===============
3060 idActor::Event_AnimState
3061 ===============
3062 */
3063 void idActor::Event_AnimState( int channel, const char *statename, int blendFrames ) {
3064  SetAnimState( channel, statename, blendFrames );
3065 }
3066 
3067 /*
3068 ===============
3069 idActor::Event_GetAnimState
3070 ===============
3071 */
3072 void idActor::Event_GetAnimState( int channel ) {
3073  const char *state;
3074 
3075  state = GetAnimState( channel );
3076  idThread::ReturnString( state );
3077 }
3078 
3079 /*
3080 ===============
3081 idActor::Event_InAnimState
3082 ===============
3083 */
3084 void idActor::Event_InAnimState( int channel, const char *statename ) {
3085  bool instate;
3086 
3087  instate = InAnimState( channel, statename );
3088  idThread::ReturnInt( instate );
3089 }
3090 
3091 /*
3092 ===============
3093 idActor::Event_FinishAction
3094 ===============
3095 */
3096 void idActor::Event_FinishAction( const char *actionname ) {
3097  if ( waitState == actionname ) {
3098  SetWaitState( "" );
3099  }
3100 }
3101 
3102 /*
3103 ===============
3104 idActor::Event_AnimDone
3105 ===============
3106 */
3107 void idActor::Event_AnimDone( int channel, int blendFrames ) {
3108  bool result;
3109 
3110  switch( channel ) {
3111  case ANIMCHANNEL_HEAD :
3112  result = headAnim.AnimDone( blendFrames );
3113  idThread::ReturnInt( result );
3114  break;
3115 
3116  case ANIMCHANNEL_TORSO :
3117  result = torsoAnim.AnimDone( blendFrames );
3118  idThread::ReturnInt( result );
3119  break;
3120 
3121  case ANIMCHANNEL_LEGS :
3122  result = legsAnim.AnimDone( blendFrames );
3123  idThread::ReturnInt( result );
3124  break;
3125 
3126  default:
3127  gameLocal.Error( "Unknown anim group" );
3128  }
3129 }
3130 
3131 /*
3132 ================
3133 idActor::Event_HasAnim
3134 ================
3135 */
3136 void idActor::Event_HasAnim( int channel, const char *animname ) {
3137  if ( GetAnim( channel, animname ) ) {
3138  idThread::ReturnFloat( 1.0f );
3139  } else {
3140  idThread::ReturnFloat( 0.0f );
3141  }
3142 }
3143 
3144 /*
3145 ================
3146 idActor::Event_CheckAnim
3147 ================
3148 */
3149 void idActor::Event_CheckAnim( int channel, const char *animname ) {
3150  if ( !GetAnim( channel, animname ) ) {
3151  if ( animPrefix.Length() ) {
3152  gameLocal.Error( "Can't find anim '%s_%s' for '%s'", animPrefix.c_str(), animname, name.c_str() );
3153  } else {
3154  gameLocal.Error( "Can't find anim '%s' for '%s'", animname, name.c_str() );
3155  }
3156  }
3157 }
3158 
3159 /*
3160 ================
3161 idActor::Event_ChooseAnim
3162 ================
3163 */
3164 void idActor::Event_ChooseAnim( int channel, const char *animname ) {
3165  int anim;
3166 
3167  anim = GetAnim( channel, animname );
3168  if ( anim ) {
3169  if ( channel == ANIMCHANNEL_HEAD ) {
3170  if ( head.GetEntity() ) {
3172  return;
3173  }
3174  } else {
3176  return;
3177  }
3178  }
3179 
3180  idThread::ReturnString( "" );
3181 }
3182 
3183 /*
3184 ================
3185 idActor::Event_AnimLength
3186 ================
3187 */
3188 void idActor::Event_AnimLength( int channel, const char *animname ) {
3189  int anim;
3190 
3191  anim = GetAnim( channel, animname );
3192  if ( anim ) {
3193  if ( channel == ANIMCHANNEL_HEAD ) {
3194  if ( head.GetEntity() ) {
3196  return;
3197  }
3198  } else {
3200  return;
3201  }
3202  }
3203 
3204  idThread::ReturnFloat( 0.0f );
3205 }
3206 
3207 /*
3208 ================
3209 idActor::Event_AnimDistance
3210 ================
3211 */
3212 void idActor::Event_AnimDistance( int channel, const char *animname ) {
3213  int anim;
3214 
3215  anim = GetAnim( channel, animname );
3216  if ( anim ) {
3217  if ( channel == ANIMCHANNEL_HEAD ) {
3218  if ( head.GetEntity() ) {
3220  return;
3221  }
3222  } else {
3224  return;
3225  }
3226  }
3227 
3228  idThread::ReturnFloat( 0.0f );
3229 }
3230 
3231 /*
3232 ================
3233 idActor::Event_HasEnemies
3234 ================
3235 */
3237  bool hasEnemy;
3238 
3239  hasEnemy = HasEnemies();
3240  idThread::ReturnInt( hasEnemy );
3241 }
3242 
3243 /*
3244 ================
3245 idActor::Event_NextEnemy
3246 ================
3247 */
3249  idActor *actor;
3250 
3251  if ( !ent || ( ent == this ) ) {
3252  actor = enemyList.Next();
3253  } else {
3254  if ( !ent->IsType( idActor::Type ) ) {
3255  gameLocal.Error( "'%s' cannot be an enemy", ent->name.c_str() );
3256  }
3257 
3258  actor = static_cast<idActor *>( ent );
3259  if ( actor->enemyNode.ListHead() != &enemyList ) {
3260  gameLocal.Error( "'%s' is not in '%s' enemy list", actor->name.c_str(), name.c_str() );
3261  }
3262  }
3263 
3264  for( ; actor != NULL; actor = actor->enemyNode.Next() ) {
3265  if ( !actor->fl.hidden ) {
3266  idThread::ReturnEntity( actor );
3267  return;
3268  }
3269  }
3270 
3272 }
3273 
3274 /*
3275 ================
3276 idActor::Event_ClosestEnemyToPoint
3277 ================
3278 */
3280  idActor *bestEnt = ClosestEnemyToPoint( pos );
3281  idThread::ReturnEntity( bestEnt );
3282 }
3283 
3284 /*
3285 ================
3286 idActor::Event_StopSound
3287 ================
3288 */
3289 void idActor::Event_StopSound( int channel, int netSync ) {
3290  if ( channel == SND_CHANNEL_VOICE ) {
3291  idEntity *headEnt = head.GetEntity();
3292  if ( headEnt ) {
3293  headEnt->StopSound( channel, ( netSync != 0 ) );
3294  }
3295  }
3296  StopSound( channel, ( netSync != 0 ) );
3297 }
3298 
3299 /*
3300 =====================
3301 idActor::Event_SetNextState
3302 =====================
3303 */
3304 void idActor::Event_SetNextState( const char *name ) {
3305  idealState = GetScriptFunction( name );
3306  if ( idealState == state ) {
3307  state = NULL;
3308  }
3309 }
3310 
3311 /*
3312 =====================
3313 idActor::Event_SetState
3314 =====================
3315 */
3316 void idActor::Event_SetState( const char *name ) {
3317  idealState = GetScriptFunction( name );
3318  if ( idealState == state ) {
3319  state = NULL;
3320  }
3322 }
3323 
3324 /*
3325 =====================
3326 idActor::Event_GetState
3327 =====================
3328 */
3330  if ( state ) {
3332  } else {
3333  idThread::ReturnString( "" );
3334  }
3335 }
3336 
3337 /*
3338 =====================
3339 idActor::Event_GetHead
3340 =====================
3341 */
3344 }
3345 
3346 #ifdef _D3XP
3347 /*
3348 ================
3349 idActor::Event_SetDamageGroupScale
3350 ================
3351 */
3352 void idActor::Event_SetDamageGroupScale( const char* groupName, float scale) {
3353 
3354  for( int i = 0; i < damageScale.Num(); i++ ) {
3355  if ( damageGroups[ i ] == groupName ) {
3356  damageScale[ i ] = scale;
3357  }
3358  }
3359 }
3360 
3361 /*
3362 ================
3363 idActor::Event_SetDamageGroupScaleAll
3364 ================
3365 */
3366 void idActor::Event_SetDamageGroupScaleAll( float scale ) {
3367 
3368  for( int i = 0; i < damageScale.Num(); i++ ) {
3369  damageScale[ i ] = scale;
3370  }
3371 }
3372 
3373 void idActor::Event_GetDamageGroupScale( const char* groupName ) {
3374 
3375  for( int i = 0; i < damageScale.Num(); i++ ) {
3376  if ( damageGroups[ i ] == groupName ) {
3378  return;
3379  }
3380  }
3381 
3383 }
3384 
3385 void idActor::Event_SetDamageCap( float _damageCap ) {
3386  damageCap = _damageCap;
3387 }
3388 
3389 void idActor::Event_SetWaitState( const char* waitState) {
3390  SetWaitState(waitState);
3391 }
3392 
3393 void idActor::Event_GetWaitState() {
3394  if(WaitState()) {
3396  } else {
3398  }
3399 }
3400 #endif
virtual const idVec3 & GetOrigin(int id=0) const =0
jointHandle_t
Definition: Model.h:156
const idEventDef AI_DisableEyeFocus("disableEyeFocus")
void Event_PlayCycle(int channel, const char *name)
Definition: Actor.cpp:2720
const idEventDef AI_SetSyncedAnimWeight("setSyncedAnimWeight","ddf")
const idEventDef AI_PlayCycle("playCycle","ds", 'd')
void Event_GetHead(void)
Definition: Actor.cpp:3342
renderEntity_t renderEntity
Definition: Entity.h:371
bool TracePoint(trace_t &results, const idVec3 &start, const idVec3 &end, int contentMask, const idEntity *passEntity)
Definition: Clip.h:333
void Restore(idRestoreGame *savefile)
Definition: IK.cpp:360
int GetChannelForJoint(jointHandle_t joint) const
float GetFloat(const char *key, const char *defaultString="0") const
Definition: Dict.h:248
static const float INFINITY
Definition: Math.h:218
const function_t * idealState
Definition: Actor.h:238
bool GetJointTransform(jointHandle_t jointHandle, int currenttime, idVec3 &offset, idMat3 &axis)
virtual void GetAASLocation(idAAS *aas, idVec3 &pos, int &areaNum) const
Definition: Actor.cpp:1905
virtual bool LoadAF(void)
Definition: Actor.cpp:1111
virtual bool Init(idEntity *self, const char *anim, const idVec3 &modelOffset)
Definition: IK.cpp:423
void WriteString(const char *string)
Definition: SaveGame.cpp:231
float Normalize(void)
Definition: Vector.h:646
void SetCycleCount(int count)
bool PointVisible(const idVec3 &point) const
Definition: Actor.cpp:1534
int GetInt(const char *key, const char *defaultString="0") const
Definition: Dict.h:252
void Event_SetNextState(const char *name)
Definition: Actor.cpp:3304
idList< idAttachInfo > attachments
Definition: Actor.h:269
assert(prefInfo.fullscreenBtn)
void StopAnim(int frames)
Definition: Actor.cpp:179
virtual void Evaluate(void)
Definition: IK.cpp:563
virtual const idSoundShader * FindSound(const char *name, bool makeDefault=true)=0
const idDict * FindEntityDefDict(const char *name, bool makeDefault=true) const
void SyncAnimChannels(int channelNum, int fromChannelNum, int currenttime, int blendTime)
void Link(idClip &clp)
Definition: Clip.cpp:545
virtual const idVec3 & GetGravityNormal(void) const =0
void Restore(idRestoreGame *savefile)
Definition: Game_local.h:661
virtual idThread * ConstructScriptObject(void)
Definition: Actor.cpp:1290
void EndThread(void)
void Event_HasAnim(int channel, const char *name)
Definition: Actor.cpp:3136
void Event_StopSound(int channel, int netsync)
Definition: Actor.cpp:3289
void SetContactFrictionDent(const float dent, const float start, const float end)
virtual void UnlinkCombat(void)
Definition: Actor.cpp:1634
idLinkList< idActor > enemyNode
Definition: Actor.h:119
virtual idAnimator * GetAnimator(void)
Definition: Entity.cpp:1566
void CallFunction(const function_t *func, bool clearStack)
void WriteObject(const idClass *obj)
Definition: SaveGame.cpp:329
idVec3 GetCenter(void) const
Definition: Bounds.h:211
const idEventDef AI_AnimState("animState","dsd")
void ClearBody(void)
Definition: AFEntity.cpp:303
virtual void DeconstructScriptObject(void)
Definition: Entity.cpp:3227
bool GetFloorPos(float max_dist, idVec3 &floorpos) const
Definition: Entity.cpp:2821
idClip clip
Definition: Game_local.h:296
void Event_DisableEyeFocus(void)
Definition: Actor.cpp:2505
void Printf(const char *fmt,...) const id_attribute((format(printf
Definition: Game_local.cpp:699
void UpdateModel(void)
Definition: Entity.cpp:1269
void Event_EnableWalkIK(void)
Definition: Actor.cpp:2530
int GetDamageForLocation(int damage, int location)
Definition: Actor.cpp:2436
void Stop(void)
Definition: AF.cpp:1042
const idEventDef AI_EnableEyeFocus("enableEyeFocus")
struct idEntity::entityFlags_s fl
void Attach(idEntity *ent)
Definition: Actor.cpp:1758
void BindToJoint(idEntity *master, const char *jointname, bool orientated)
Definition: Entity.cpp:1921
type * GetEntity(void) const
Definition: Game_local.h:695
bool SetType(const char *typeName)
bool UpdateState(void)
Definition: Actor.cpp:301
void Event_Footstep(void)
Definition: Actor.cpp:2521
const idEventDef AI_DisablePain("disablePain")
const char * GetTypeName(void) const
idAnimState()
Definition: Actor.cpp:46
idEntityPtr< idEntity > ent
Definition: Actor.h:101
const idStr & GetKey(void) const
Definition: Dict.h:52
void SetNum(int newnum, bool resize=true)
Definition: List.h:289
bool SetSyncedAnimWeight(int num, float weight)
const idEventDef AI_GetBlendFrames("getBlendFrames","d", 'd')
idEntity * GetBindMaster(void) const
Definition: Entity.cpp:2153
GLint location
Definition: glext.h:3631
void ManualDelete(void)
void StopRagdoll(void)
Definition: Actor.cpp:1708
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:4804
idMat3 Transpose(void) const
Definition: Matrix.h:677
idRandom random
Definition: Game_local.h:291
idVec3 modelOffset
Definition: Actor.h:221
int Length(void) const
Definition: Str.h:702
void SetAxis(const idMat3 &axis)
Definition: Entity.cpp:2796
void void void void void Error(const char *fmt,...) const id_attribute((format(printf
Definition: Game_local.cpp:783
const int ANIMCHANNEL_ALL
Definition: Anim.h:41
void Restore(idRestoreGame *savefile)
Definition: Actor.cpp:914
bool isMultiplayer
Definition: Game_local.h:325
int NumJoints(void) const
idScriptObject scriptObject
Definition: Entity.h:123
int blink_max
Definition: Actor.h:254
idAngles GetAngles(const char *key, const char *defaultString=NULL) const
Definition: Dict.h:278
bool IsType(const idTypeInfo &c) const
Definition: Class.h:337
void SetCombatModel(void)
Definition: Actor.cpp:1581
virtual bool GetPhysicsToVisualTransform(idVec3 &origin, idMat3 &axis)
Definition: Actor.cpp:1219
bool HasObject(void) const
bool idleAnim
Definition: Actor.h:64
void CycleAnim(int anim)
Definition: Actor.cpp:201
jointHandle_t soundJoint
Definition: Actor.h:243
void Event_NextEnemy(idEntity *ent)
Definition: Actor.cpp:3248
idClipModel * GetCombatModel(void) const
Definition: Actor.cpp:1604
idLinkList< idActor > enemyList
Definition: Actor.h:120
float z
Definition: Vector.h:320
const int ANIMCHANNEL_EYELIDS
Definition: Anim.h:45
const idKeyValue * MatchPrefix(const char *prefix, const idKeyValue *lastMatch=NULL) const
Definition: Dict.cpp:523
jointHandle_t from
Definition: Actor.h:107
static void DropItems(idAnimatedEntity *ent, const char *type, idList< idEntity * > *list)
Definition: Item.cpp:1873
virtual void DamageFeedback(idEntity *victim, idEntity *inflictor, int &damage)
Definition: Entity.cpp:3040
void PlayAnim(int channelNum, int animnum, int currenttime, int blendTime)
void Strip(const char c)
Definition: Str.h:915
void SetGranularity(int newgranularity)
Definition: List.h:305
idList< float > damageScale
Definition: Actor.h:230
const idEventDef EV_EnableLegIK("EnableLegIK","d")
void SetCombatModel(void)
Definition: AFEntity.cpp:462
jointHandle_t GetJointHandle(const char *name) const
void SetEyeHeight(float height)
Definition: Actor.cpp:1427
const idEventDef AI_SetNextState("setNextState","s")
const idEventDef AI_AnimLength("animLength","ds", 'f')
void Event_GetPainAnim(void)
Definition: Actor.cpp:2593
bool isClient
Definition: Game_local.h:327
Definition: Vector.h:316
void ReadJoint(jointHandle_t &value)
Definition: SaveGame.cpp:931
case const float
Definition: Callbacks.cpp:62
void ReadBool(bool &value)
Definition: SaveGame.cpp:976
const idEventDef AI_AnimDistance("animDistance","ds", 'f')
void PlayFootStepSound(void)
Definition: Actor.cpp:2469
void PlayAnim(int anim)
Definition: Actor.cpp:189
void Event_IdleAnim(int channel, const char *name)
Definition: Actor.cpp:2794
#define IK_ANIM
Definition: IK.h:40
void Event_EnableLegIK(int num)
Definition: Actor.cpp:2548
bool IsIdle(void) const
Definition: Actor.cpp:250
idPhysics_AF * GetPhysics(void)
Definition: AF.h:77
int team
Definition: Actor.h:115
void Event_GetBlendFrames(int channel)
Definition: Actor.cpp:3038
virtual int GetDefaultSurfaceType(void) const
Definition: Actor.cpp:1081
virtual void Gib(const idVec3 &dir, const char *damageDefName)
Definition: AFEntity.cpp:1217
int blink_time
Definition: Actor.h:252
virtual void SetLinearVelocity(const idVec3 &newLinearVelocity, int id=0)=0
virtual void ProjectOverlay(const idVec3 &origin, const idVec3 &dir, float size, const char *material)
Definition: Actor.cpp:1090
Definition: Token.h:71
void SetJointPos(jointHandle_t jointnum, jointModTransform_t transform_type, const idVec3 &pos)
virtual int PointReachableAreaNum(const idVec3 &origin, const idBounds &bounds, const int areaFlags) const =0
bool allowEyeFocus
Definition: Actor.h:264
virtual void LinkCombat(void)
Definition: Actor.cpp:1613
const char * GetClassname(void) const
Definition: Class.cpp:593
GLuint src
Definition: glext.h:5390
const int ANIMCHANNEL_HEAD
Definition: Anim.h:44
#define MASK_OPAQUE
Definition: Game_local.h:740
void Set(const char *key, const char *value)
Definition: Dict.cpp:275
bool cinematic
Definition: Entity.h:127
void Identity(void)
Definition: Matrix.h:591
void CopyJointsFromBodyToHead(void)
Definition: Actor.cpp:748
const idEventDef AI_NextEnemy("nextEnemy","E", 'e')
int ReadTokenOnLine(idToken *token)
Definition: Lexer.cpp:1172
virtual void SpawnGibs(const idVec3 &dir, const char *damageDefName)
Definition: AFEntity.cpp:1162
idDict spawnArgs
Definition: Entity.h:122
idBounds boundingBoxes[MAX_AAS_BOUNDING_BOXES]
Definition: AASFile.h:215
int i
Definition: process.py:33
void SetStartTime(int startTime)
const idVec3 & TotalMovementDelta(int animnum) const
const char * Name(void) const
virtual void UnlinkCombat(void)
Definition: AFEntity.cpp:501
idStr waitState
Definition: Actor.h:258
void SetAnimator(idAnimator *a)
Definition: AF.h:63
bool disabled
Definition: Actor.h:96
idAnimState headAnim
Definition: Actor.h:259
GLuint GLuint num
Definition: glext.h:5390
Boolean result
void WriteVec3(const idVec3 &vec)
Definition: SaveGame.cpp:253
idAngles & Zero(void)
Definition: Angles.h:126
void Event_PlayAnim(int channel, const char *name)
Definition: Actor.cpp:2640
void SetDeltaViewAngles(const idAngles &delta)
Definition: Actor.cpp:1821
void SetThreadName(const char *name)
void SetAnimState(int channel, const char *name, int blendFrames)
Definition: Actor.cpp:1937
idAnimator * animator
Definition: Actor.h:93
const idEventDef EV_EnableWalkIK("EnableWalkIK")
int Icmp(const char *text) const
Definition: Str.h:667
void SetName(const char *name)
Definition: Entity.cpp:854
void Event_AnimDone(int channel, int blendFrames)
Definition: Actor.cpp:3107
#define EVENT(event, function)
Definition: Class.h:53
const idEventDef AI_EnablePain("enablePain")
idMat3 viewAxis
Definition: Actor.h:117
int lastAnimBlendFrames
Definition: Actor.h:67
bool Load(idEntity *ent, const char *fileName)
Definition: AF.cpp:795
idClipModel * combatModel
Definition: AFEntity.h:193
const idEventDef EV_StopSound("stopSound","dd")
float fraction
void Event_DisableWalkIK(void)
Definition: Actor.cpp:2539
void SetJointAxis(jointHandle_t jointnum, jointModTransform_t transform_type, const idMat3 &mat)
void WriteJoint(const jointHandle_t value)
Definition: SaveGame.cpp:177
void ClearObject(void)
void WriteBool(const bool value)
Definition: SaveGame.cpp:222
virtual void Killed(idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location)
Definition: Entity.cpp:3163
void Event_PreventPain(float duration)
Definition: Actor.cpp:2566
idAnimator animator
Definition: Entity.h:534
const idEventDef AI_InAnimState("inAnimState","ds", 'd')
void ManualControl(void)
virtual renderView_t * GetRenderView()
Definition: Entity.cpp:1577
bool IsHidden(void) const
Definition: Entity.cpp:1217
bool HasEnemies(void) const
Definition: Actor.cpp:1830
idEntity * SpawnEntityType(const idTypeInfo &classdef, const idDict *args=NULL, bool bIsClientReadSnapshot=false)
idActor * self
Definition: Actor.h:92
bool AnimDone(int blendFrames) const
Definition: Actor.cpp:231
void void void Warning(const char *fmt,...) const id_attribute((format(printf
Definition: Game_local.cpp:735
const idEventDef EV_DisableWalkIK("DisableWalkIK")
bool CanSee(idEntity *ent, bool useFOV) const
Definition: Actor.cpp:1500
int AnimNum(void) const
void EnableLeg(int num)
Definition: IK.cpp:822
idAngles deltaViewAngles
Definition: Actor.h:223
virtual const idBounds & GetBounds(int id=-1) const =0
const char * AnimName(void) const
virtual bool OnLadder(void) const
Definition: Actor.cpp:1896
bool StartSoundShader(const idSoundShader *shader, const s_channelType channel, int soundShaderFlags, bool broadcast, int *length)
Definition: Entity.cpp:1656
void GetPhysicsToVisualTransform(idVec3 &origin, idMat3 &axis) const
Definition: AF.cpp:404
int channel
Definition: Actor.h:95
void SetFOV(float fov)
Definition: Actor.cpp:1418
void KillBox(idEntity *ent, bool catch_teleport=false)
const char * AnimFullName(void) const
void ClearAllJoints(void)
Definition: Lexer.h:137
const idEventDef AI_SetBlendFrames("setBlendFrames","dd")
virtual void Show(void)
Definition: Entity.cpp:1239
idVec3 GetEyePosition(void) const
Definition: Actor.cpp:1454
const idMaterial * material
void DisableDebugInfo(void)
void ShutdownThreads(void)
Definition: Actor.cpp:1257
const idEventDef AI_IdleAnim("idleAnim","ds", 'd')
virtual const contactInfo_t & GetContact(int num) const =0
void Rest(void)
Definition: AF.cpp:1053
const idEventDef EV_FootstepLeft("leftFoot")
jointModTransform_t
Definition: Anim.h:84
void SetTimeScaleRamp(const float start, const float end)
idEntityPtr< idAFAttachment > head
Definition: Actor.h:233
int GetAnim(int channel, const char *name)
Definition: Actor.cpp:2069
idPhysics * GetPhysics(void) const
Definition: Entity.cpp:2607
const char * GetString(const char *key, const char *defaultString="") const
Definition: Dict.h:240
bool SpawnEntityDef(const idDict &args, idEntity **ent=NULL, bool setDefaults=true)
void ReadFloat(float &value)
Definition: SaveGame.cpp:967
const idEventDef AI_OverrideAnim("overrideAnim","d")
float Length(void) const
Definition: Vector.h:631
const idEventDef AI_GetAnimState("getAnimState","d", 's')
idWorldspawn * world
Definition: Game_local.h:280
float RandomFloat(void)
Definition: Random.h:82
type & Alloc(void)
Definition: List.h:624
void Event_ClosestEnemyToPoint(const idVec3 &pos)
Definition: Actor.cpp:3279
void Event_OverrideAnim(int channel)
Definition: Actor.cpp:2950
bool StartSound(const char *soundName, const s_channelType channel, int soundShaderFlags, bool broadcast, int *length)
Definition: Entity.cpp:1622
const idEventDef AI_GetHead("getHead", NULL, 'e')
idVec3 vec3_origin(0.0f, 0.0f, 0.0f)
const idAngles & GetDeltaViewAngles(void) const
Definition: Actor.cpp:1812
idAnimState legsAnim
Definition: Actor.h:261
int pain_threshold
Definition: Actor.h:227
const idEventDef AI_HasEnemies("hasEnemies", NULL, 'd')
idCVar g_debugDamage("g_debugDamage","0", CVAR_GAME|CVAR_BOOL,"")
void DoneProcessing(void)
virtual bool GetPhysicsToSoundTransform(idVec3 &origin, idMat3 &axis)
Definition: Actor.cpp:1234
GLuint GLuint end
Definition: glext.h:2845
bool allowPain
Definition: Actor.h:263
const idEventDef AI_PreventPain("preventPain","f")
void WriteFloat(const float value)
Definition: SaveGame.cpp:213
const function_t * state
Definition: Actor.h:237
idActor(void)
Definition: Actor.cpp:429
void Event_EnablePain(void)
Definition: Actor.cpp:2584
void Spawn(void)
Definition: Actor.cpp:516
jointModTransform_t mod
Definition: Actor.h:106
const idEventDef AI_EnableAnim("enableAnim","dd")
static const char * sufaceTypeNames[MAX_SURFACE_TYPES]
Definition: Game_local.h:337
void ClearAllAnims(int currentTime, int cleartime)
void Event_StopAnim(int channel, int frames)
Definition: Actor.cpp:2615
bool GetBool(const char *key, const char *defaultString="0") const
Definition: Dict.h:256
Definition: Dict.h:65
#define NULL
Definition: Lib.h:88
void Event_DisableLegIK(int num)
Definition: Actor.cpp:2557
idAnimBlend * CurrentAnim(int channelNum)
void void DPrintf(const char *fmt,...) const id_attribute((format(printf
Definition: Game_local.cpp:715
static void DropAFs(idEntity *ent, const char *type, idList< idEntity * > *list)
Definition: AFEntity.cpp:892
int painTime
Definition: Actor.h:267
int GetInteger(void) const
Definition: CVarSystem.h:143
idVec3 GetVector(const char *key, const char *defaultString=NULL) const
Definition: Dict.h:260
bool GetJointLocalTransform(jointHandle_t jointHandle, int currentTime, idVec3 &offset, idMat3 &axis)
idAnimState torsoAnim
Definition: Actor.h:260
void Save(idSaveGame *savefile) const
Definition: IK.cpp:297
int rank
Definition: Actor.h:116
const char * GetDamageGroup(int location)
Definition: Actor.cpp:2449
idStr animPrefix
Definition: Actor.h:247
idEntity * GetNextTeamEntity(void) const
Definition: Entity.cpp:2189
virtual void SetOrigin(const idVec3 &newOrigin, int id=-1)=0
const idAnim * GetAnim(int index) const
const idEventDef AI_PlayAnim("playAnim","ds", 'd')
void CycleAnim(int channelNum, int animnum, int currenttime, int blendtime)
static void ReturnFloat(float value)
const idEventDef AI_SetAnimPrefix("setAnimPrefix","s")
const idEventDef EV_DisableLegIK("DisableLegIK","d")
void GetJointList(const char *jointnames, idList< jointHandle_t > &jointList) const
virtual void Teleport(const idVec3 &origin, const idAngles &angles, idEntity *destination)
Definition: Actor.cpp:1793
void DisableLeg(int num)
Definition: IK.cpp:831
#define CM_CLIP_EPSILON
idThread * thread
Definition: Actor.h:94
bool use_combat_bbox
Definition: Actor.h:232
void BecomeIdle(void)
Definition: Actor.cpp:213
const char * WaitState(void) const
Definition: Actor.cpp:2036
idActor * ClosestEnemyToPoint(const idVec3 &pos)
Definition: Actor.cpp:1847
const idStr & GetValue(void) const
Definition: Dict.h:53
void Event_InAnimState(int channel, const char *name)
Definition: Actor.cpp:3084
virtual const idMat3 & GetAxis(int id=0) const =0
virtual idAnimator * GetAnimator(void)
Definition: Entity.cpp:5213
bool IsInitialized(void) const
Definition: IK.cpp:113
const function_t * GetConstructor(void) const
animFlags_t GetAnimFlags(void) const
Definition: Actor.cpp:259
void Disable(void)
Definition: Actor.cpp:291
idGameLocal gameLocal
Definition: Game_local.cpp:64
void SetBool(const char *key, bool val)
Definition: Dict.h:196
float LengthSqr(void) const
Definition: Vector.h:635
void ForceUpdate(void)
void Restore(idRestoreGame *savefile)
Definition: Actor.cpp:94
const animFlags_t GetAnimFlags(int animnum) const
#define END_CLASS
Definition: Class.h:54
const idEventDef EV_Footstep("footstep")
int GetCycleCount(void) const
void Shutdown(void)
Definition: Actor.cpp:139
#define DEG2RAD(a)
Definition: Math.h:56
bool InAnimState(int channel, const char *name) const
Definition: Actor.cpp:2003
void SetJointFrictionDent(const float dent, const float start, const float end)
void Init(idActor *owner, idAnimator *_animator, int animchannel)
Definition: Actor.cpp:119
void FinishSetup(void)
Definition: Actor.cpp:653
void SetState(const char *name, int blendFrames)
Definition: Actor.cpp:149
virtual void Hide(void)
Definition: Entity.cpp:1226
const surfTypes_t GetSurfaceType(void) const
Definition: Material.h:503
virtual void DisableClip(void)=0
void Enable(int blendFrames)
Definition: Actor.cpp:275
idStrList damageGroups
Definition: Actor.h:229
GLenum GLsizei GLsizei height
Definition: glext.h:2856
const char * ToString(int precision=2) const
Definition: Vector.cpp:221
void WriteInt(const int value)
Definition: SaveGame.cpp:168
idActor * EnemyWithMostHealth()
Definition: Actor.cpp:1876
void SetupDamageGroups(void)
Definition: Actor.cpp:2387
int channel
Definition: Actor.h:102
float EyeHeight(void) const
Definition: Actor.cpp:1436
void RemoveAttachments(void)
Definition: Actor.cpp:1740
const idEventDef AI_HasAnim("hasAnim","ds", 'f')
idDeclManager * declManager
void SetupHead(void)
Definition: Actor.cpp:673
void WriteMat3(const idMat3 &mat)
Definition: SaveGame.cpp:309
#define SEC2MS(t)
Definition: Math.h:59
bool IsWaiting(void)
idCVar ai_debugScript("ai_debugScript","-1", CVAR_GAME|CVAR_INTEGER,"displays script calls for the specified monster entity number")
void ReadMat3(idMat3 &mat)
Definition: SaveGame.cpp:1064
bool IsLoaded(void) const
Definition: AF.h:65
void EnableAll(void)
Definition: IK.cpp:802
void Save(idSaveGame *savefile) const
Definition: Actor.cpp:796
const idEventDef AI_GetPainAnim("getPainAnim", NULL, 's')
int ExpectTokenString(const char *string)
Definition: Lexer.cpp:919
int health
Definition: Entity.h:134
idEntity * GetTraceEntity(const trace_t &trace) const
idVec3 vieworg
Definition: RenderWorld.h:215
bool finalBoss
Definition: Actor.h:265
int AnimLength(int animnum) const
const idEventDef AI_FinishAction("finishAction","s")
int Append(const type &obj)
Definition: List.h:646
bool HasAnim(const char *name) const
void PlayIdleAnim(int blendTime)
Definition: AFEntity.cpp:439
void Event_AnimState(int channel, const char *name, int blendFrames)
Definition: Actor.cpp:3063
Definition: Matrix.h:333
void Event_GetState(void)
Definition: Actor.cpp:3329
void Event_EnableEyeFocus(void)
Definition: Actor.cpp:2495
void StartFromCurrentPose(int inheritVelocityTime)
Definition: AF.cpp:999
static void ReturnString(const char *text)
void UpdateAnimState(void)
Definition: Actor.cpp:2058
void WriteAngles(const idAngles &angles)
Definition: SaveGame.cpp:318
virtual ~idActor(void)
Definition: Actor.cpp:483
void UpdateVisuals(void)
Definition: Entity.cpp:1310
void SyncAnimChannels(int channel, int syncToChannel, int blendFrames)
Definition: Actor.cpp:2101
const char * AnimFullName(int animnum) const
bool GetBool(void) const
Definition: CVarSystem.h:142
tuple f
Definition: idal.py:89
void SetWaitState(const char *_waitstate)
Definition: Actor.cpp:2049
jointHandle_t leftEyeJoint
Definition: Actor.h:241
bool LoadModel(const char *name)
Definition: Clip.cpp:215
const idEventDef EV_FootstepRight("rightFoot")
Definition: Actor.h:111
virtual void SpawnGibs(const idVec3 &dir, const char *damageDefName)
Definition: Actor.cpp:2375
int Num(void) const
Definition: List.h:265
#define AREA_REACHABLE_WALK
Definition: AASFile.h:74
void DisableAll(void)
Definition: IK.cpp:812
idMat3 ToMat3(void) const
Definition: Angles.cpp:199
virtual bool Pain(idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location)
Definition: Actor.cpp:2292
virtual const idAASSettings * GetSettings(void) const =0
void Event_SetState(const char *name)
Definition: Actor.cpp:3316
int blink_anim
Definition: Actor.h:251
int modelDefHandle
Definition: Entity.h:372
const GLcharARB * name
Definition: glext.h:3629
GLsizeiptr size
Definition: glext.h:3112
const function_t * GetFunction(const char *name) const
void Event_FinishAction(const char *name)
Definition: Actor.cpp:3096
virtual void GetAIAimTargets(const idVec3 &lastSightPos, idVec3 &headPos, idVec3 &chestPos)
Definition: Actor.cpp:1553
virtual bool ShouldConstructScriptObjectAtSpawn(void) const
Definition: Actor.cpp:1278
bool GetJointWorldTransform(jointHandle_t jointHandle, int currentTime, idVec3 &offset, idMat3 &axis)
Definition: Entity.cpp:5248
idVec3 eyeOffset
Definition: Actor.h:220
virtual bool UpdateAnimationControllers(void)
Definition: Actor.cpp:1719
virtual void Damage(idEntity *inflictor, idEntity *attacker, const idVec3 &dir, const char *damageDefName, const float damageScale, const int location)
Definition: Actor.cpp:2203
#define CLASS_DECLARATION(nameofsuperclass, nameofclass)
Definition: Class.h:110
Definition: Str.h:116
virtual void LinkCombat(void)
Definition: AFEntity.cpp:486
void Event_EnableAnim(int channel, int blendFrames)
Definition: Actor.cpp:2985
idList< copyJoints_t > copyJoints
Definition: Actor.h:234
const function_t * GetScriptFunction(const char *funcname)
Definition: Actor.cpp:1328
const idEventDef AI_ChooseAnim("chooseAnim","ds", 's')
virtual void Hide(void)
Definition: AFEntity.cpp:352
int animBlendFrames
Definition: Actor.h:66
void Save(idSaveGame *savefile) const
Definition: Game_local.h:656
void ReadVec3(idVec3 &vec)
Definition: SaveGame.cpp:1011
idStr painAnim
Definition: Actor.h:248
virtual void Show(void)
Definition: Actor.cpp:1050
void Event_GetAnimState(int channel)
Definition: Actor.cpp:3072
static void ReturnEntity(idEntity *ent)
void SetBody(idEntity *bodyEnt, const char *headModel, jointHandle_t attachJoint)
Definition: AFEntity.cpp:286
const char * c_str(void) const
Definition: Str.h:487
void Error(const char *fmt,...) const id_attribute((format(printf
void EnableDebugInfo(void)
void Clear(int channelNum, int currentTime, int cleartime)
void ClearAFPose(void)
virtual void Hide(void)
Definition: Actor.cpp:1024
bool Disabled(void) const
Definition: Actor.cpp:222
int pain_delay
Definition: Actor.h:226
void ReadAngles(idAngles &angles)
Definition: SaveGame.cpp:1073
ID_INLINE int FRAME2MS(int framenum)
Definition: Anim.h:48
const char * GetJointName(jointHandle_t handle) const
void BecomeActive(int flags)
Definition: Entity.cpp:995
idRenderSystemLocal tr
virtual void GetViewPos(idVec3 &origin, idMat3 &axis) const
Definition: Actor.cpp:1463
const int ANIMCHANNEL_TORSO
Definition: Anim.h:42
virtual renderView_t * GetRenderView()
Definition: Actor.cpp:1563
const idEventDef EV_Remove("<immediateremove>", NULL)
jointHandle_t to
Definition: Actor.h:108
void Event_HasEnemies(void)
Definition: Actor.cpp:3236
int GetEndTime(void) const
void SetFrame(int channelNum, int animnum, int frame, int currenttime, int blendtime)
virtual void Show(void)
Definition: AFEntity.cpp:362
virtual const idDeclSkin * FindSkin(const char *name, bool makeDefault=true)=0
idVec3 EyeOffset(void) const
Definition: Actor.cpp:1445
void CheckBlink(void)
Definition: Actor.cpp:1197
bool CheckFOV(const idVec3 &pos) const
Definition: Actor.cpp:1473
const idEventDef AI_SetState("setState","s")
const int ANIMCHANNEL_LEGS
Definition: Anim.h:43
bool prevent_idle_override
Definition: Anim.h:175
int GetStartTime(void) const
int pain_debounce_time
Definition: Actor.h:225
virtual void PushPointIntoAreaNum(int areaNum, idVec3 &origin) const =0
float dot(float a[], float b[])
Definition: Model_lwo.cpp:3883
Definition: Light.h:44
void Event_SetAnimPrefix(const char *name)
Definition: Actor.cpp:2606
void ClearPain(void)
Definition: Actor.cpp:2283
virtual void Restart(void)
Definition: Actor.cpp:783
~idAnimState()
Definition: Actor.cpp:62
const char * GetEntityDefName(void) const
Definition: Entity.cpp:842
const idEventDef AI_CheckAnim("checkAnim","ds")
const idEventDef AI_GetState("getState", NULL, 's')
char * va(const char *fmt,...)
Definition: Str.cpp:1568
int blink_min
Definition: Actor.h:253
void Event_AnimDistance(int channel, const char *animname)
Definition: Actor.cpp:3212
void Event_AnimLength(int channel, const char *animname)
Definition: Actor.cpp:3188
void SetOrigin(const idVec3 &org)
Definition: Entity.cpp:2784
bool PostEventMS(const idEventDef *ev, int time)
Definition: Class.cpp:666
int entityNumber
Definition: Entity.h:111
idMat3 viewaxis
Definition: RenderWorld.h:216
idStr name
Definition: Entity.h:121
void Unlink(void)
Definition: Clip.cpp:491
const idEventDef AI_StopAnim("stopAnim","dd")
idEntity * GetEntity(void) const
void Event_SetSyncedAnimWeight(int channel, int anim, float weight)
Definition: Actor.cpp:2901
void Event_DisablePain(void)
Definition: Actor.cpp:2575
virtual void ProjectOverlay(const idVec3 &origin, const idVec3 &dir, float size, const char *material)
Definition: Entity.cpp:1418
bool IsActive(void) const
Definition: AF.h:74
idStr state
Definition: Actor.h:65
void Zero(void)
Definition: Vector.h:415
void ReadString(idStr &string)
Definition: SaveGame.cpp:985
idIK_Walk walkIK
Definition: Actor.h:245
bool Execute(void)
static void ReturnInt(int value)
idThread * scriptThread
Definition: Actor.h:257
int sprintf(idStr &string, const char *fmt,...)
Definition: Str.cpp:1528
virtual bool UpdateAnimationControllers(void)
Definition: AFEntity.cpp:786
void ReadInt(int &value)
Definition: SaveGame.cpp:922
void Event_ChooseAnim(int channel, const char *animname)
Definition: Actor.cpp:3164
jointHandle_t rightEyeJoint
Definition: Actor.h:242
const idEventDef AI_AnimDone("animDone","dd", 'd')
GLuint start
Definition: glext.h:2845
void StopSound(const s_channelType channel, bool broadcast)
Definition: Entity.cpp:1713
virtual void Gib(const idVec3 &dir, const char *damageDefName)
Definition: Actor.cpp:2167
void UpdateScript(void)
Definition: Actor.cpp:1375
void SetState(const function_t *newState)
Definition: Actor.cpp:1344
bool StartRagdoll(void)
Definition: Actor.cpp:1651
void SetupBody(void)
Definition: Actor.cpp:1126
bool StripLeadingOnce(const char *string)
Definition: Str.cpp:498
#define MS2SEC(t)
Definition: Math.h:60
const idEventDef AI_ClosestEnemyToPoint("closestEnemyToPoint","v", 'e')
void Event_SetBlendFrames(int channel, int blendFrames)
Definition: Actor.cpp:3010
void ReadObject(idClass *&obj)
Definition: SaveGame.cpp:1083
Definition: AAS.h:75
float fovDot
Definition: Actor.h:219
void void Warning(const char *fmt,...) const id_attribute((format(printf
void Event_CheckAnim(int channel, const char *animname)
Definition: Actor.cpp:3149
const char * GetAnimState(int channel) const
Definition: Actor.cpp:1977
void Clear(void)
Definition: List.h:184
void Save(idSaveGame *savefile) const
Definition: Actor.cpp:71