home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2006 March / Gamestar_82_2006-03_dvd.iso / DVDStar / Editace / quake4_sdkv10.exe / source / game / Entity.cpp < prev    next >
C/C++ Source or Header  |  2005-11-14  |  170KB  |  6,771 lines

  1. #include "../idlib/precompiled.h"
  2. #pragma hdrstop
  3.  
  4. #include "Game_local.h"
  5.  
  6. // RAVEN BEGIN
  7. // bdube: client effects
  8. #include "client/ClientEffect.h"
  9. //mcg: need to know team for AddDamageEffects
  10. #include "ai/AI_Manager.h"
  11. // RAVEN END
  12.  
  13. /*
  14. ===============================================================================
  15.  
  16.     idEntity
  17.  
  18. ===============================================================================
  19. */
  20.  
  21. // overridable events
  22. const idEventDef EV_PostSpawn( "<postspawn>", NULL );
  23. const idEventDef EV_FindTargets( "<findTargets>", NULL );
  24. const idEventDef EV_Touch( "<touch>", "et" );
  25. const idEventDef EV_GetName( "getName", NULL, 's' );
  26. const idEventDef EV_SetName( "setName", "s" );
  27. const idEventDef EV_Activate( "activate", "e" );
  28. const idEventDef EV_ActivateTargets( "activateTargets", "e" );
  29. const idEventDef EV_NumTargets( "numTargets", NULL, 'f' );
  30. const idEventDef EV_GetTarget( "getTarget", "f", 'e' );
  31. const idEventDef EV_RandomTarget( "randomTarget", "s", 'e' );
  32. const idEventDef EV_Bind( "bind", "e" );
  33. const idEventDef EV_BindPosition( "bindPosition", "e" );
  34. const idEventDef EV_BindToJoint( "bindToJoint", "esf" );
  35. const idEventDef EV_Unbind( "unbind", NULL );
  36. const idEventDef EV_RemoveBinds( "removeBinds" );
  37. const idEventDef EV_SpawnBind( "<spawnbind>", NULL );
  38. const idEventDef EV_SetOwner( "setOwner", "e" );
  39. const idEventDef EV_SetModel( "setModel", "s" );
  40. const idEventDef EV_SetSkin( "setSkin", "s" );
  41. const idEventDef EV_GetWorldOrigin( "getWorldOrigin", NULL, 'v' );
  42. const idEventDef EV_SetWorldOrigin( "setWorldOrigin", "v" );
  43. const idEventDef EV_GetOrigin( "getOrigin", NULL, 'v' );
  44. const idEventDef EV_SetOrigin( "setOrigin", "v" );
  45. const idEventDef EV_GetAngles( "getAngles", NULL, 'v' );
  46. const idEventDef EV_SetAngles( "setAngles", "v" );
  47. const idEventDef EV_GetLinearVelocity( "getLinearVelocity", NULL, 'v' );
  48. const idEventDef EV_SetLinearVelocity( "setLinearVelocity", "v" );
  49. const idEventDef EV_GetAngularVelocity( "getAngularVelocity", NULL, 'v' );
  50. const idEventDef EV_SetAngularVelocity( "setAngularVelocity", "v" );
  51. const idEventDef EV_GetSize( "getSize", NULL, 'v' );
  52. const idEventDef EV_SetSize( "setSize", "vv" );
  53. const idEventDef EV_GetMins( "getMins", NULL, 'v' );
  54. const idEventDef EV_GetMaxs( "getMaxs", NULL, 'v' );
  55. const idEventDef EV_IsHidden( "isHidden", NULL, 'd' );
  56. const idEventDef EV_Hide( "hide", NULL );
  57. const idEventDef EV_Show( "show", NULL );
  58. const idEventDef EV_Touches( "touches", "E", 'd' );
  59. const idEventDef EV_ClearSignal( "clearSignal", "d" );
  60. const idEventDef EV_GetShaderParm( "getShaderParm", "d", 'f' );
  61. const idEventDef EV_SetShaderParm( "setShaderParm", "df" );
  62. const idEventDef EV_SetShaderParms( "setShaderParms", "ffff" );
  63. const idEventDef EV_SetColor( "setColor", "fff" );
  64. const idEventDef EV_GetColor( "getColor", NULL, 'v' );
  65. const idEventDef EV_CacheSoundShader( "cacheSoundShader", "s" );
  66. const idEventDef EV_StartSoundShader( "startSoundShader", "sd", 'f' );
  67. const idEventDef EV_StartSound( "startSound", "sdd", 'f' );
  68. const idEventDef EV_StopSound( "stopSound", "dd" );
  69. const idEventDef EV_FadeSound( "fadeSound", "dff" );
  70. const idEventDef EV_SetGuiParm( "setGuiParm", "ss" );
  71. const idEventDef EV_SetGuiFloat( "setGuiFloat", "sf" );
  72. const idEventDef EV_GetNextKey( "getNextKey", "ss", 's' );
  73. const idEventDef EV_SetKey( "setKey", "ss" );
  74. const idEventDef EV_GetKey( "getKey", "s", 's' );
  75. const idEventDef EV_GetIntKey( "getIntKey", "s", 'f' );
  76. const idEventDef EV_GetFloatKey( "getFloatKey", "s", 'f' );
  77. const idEventDef EV_GetVectorKey( "getVectorKey", "s", 'v' );
  78. const idEventDef EV_GetEntityKey( "getEntityKey", "s", 'e' );
  79. const idEventDef EV_RestorePosition( "restorePosition" );
  80. const idEventDef EV_UpdateCameraTarget( "<updateCameraTarget>", NULL );
  81. const idEventDef EV_DistanceTo( "distanceTo", "E", 'f' );
  82. const idEventDef EV_DistanceToPoint( "distanceToPoint", "v", 'f' );
  83. const idEventDef EV_StartFx( "startFx", "s" );
  84. const idEventDef EV_HasFunction( "hasFunction", "s", 'd' );
  85. const idEventDef EV_CallFunction( "callFunction", "s" );
  86. const idEventDef EV_SetNeverDormant( "setNeverDormant", "d" );
  87.  
  88. // RAVEN BEGIN
  89. // bgeisler: go back to default skin
  90. const idEventDef EV_ClearSkin( "clearSkin");
  91. // kfuller: added events
  92. const idEventDef EV_SetContents( "setContents", "d" );
  93. const idEventDef EV_GetLastBlocker( "getLastBlocker", NULL, 'e' );
  94. const idEventDef EV_Earthquake( "earthquake", "f" );
  95. // we should probably try to integrate this with AI_PlayAnim
  96. const idEventDef EV_PlayAnim("playAnimNoChannel", "s");
  97. const idEventDef EV_PlayAnimXTimes("playAnimXTimes", "sf");
  98. // bdube: effect events
  99. const idEventDef EV_PlayEffect( "playEffect", "ssd" );
  100. const idEventDef EV_StopEffect( "stopEffect", "s" );
  101. const idEventDef EV_StopAllEffects( "stopAllEffects" );
  102. const idEventDef EV_GetHealth ( "getHealth", NULL, 'f' );
  103. // bdube: surface related events
  104. const idEventDef EV_HideSurface( "hideSurface", "s" );
  105. const idEventDef EV_ShowSurface( "showSurface", "s" );
  106. // bdube: added gui events
  107. const idEventDef EV_GuiEvent ( "guiEvent", "s" );
  108. // jscott: for playback button handling
  109. const idEventDef EV_PlaybackCallback( "playbackCallback", "ddd" );
  110. // nmckenzie:
  111. const idEventDef EV_GetBindMaster( "getBindMaster", NULL, 'e' );
  112. const idEventDef EV_ApplyImpulse( "applyImpulse", "evv" );
  113. // abahr:
  114. const idEventDef EV_RemoveNullTargets( "removeNullTargets" );
  115. const idEventDef EV_IsA( "isA", "s", 'f' );
  116. const idEventDef EV_IsSameTypeAs( "isSameTypeAs", "e", 'f' );
  117. const idEventDef EV_MatchPrefix( "matchPrefix", "ss", 's' );
  118. const idEventDef EV_ClearTargetList( "clearTargetList", "f" );
  119. // twhitaker:
  120. const idEventDef EV_AppendTarget( "appendTarget", "E", 'f' );
  121. const idEventDef EV_RemoveTarget( "removeTarget", "e" );
  122. // mekberg:
  123. const idEventDef EV_SetHealth( "setHealth", "f" );
  124. // RAVEN END
  125.  
  126. ABSTRACT_DECLARATION( idClass, idEntity )
  127.     EVENT( EV_GetName,                idEntity::Event_GetName )
  128.     EVENT( EV_SetName,                idEntity::Event_SetName )
  129.     EVENT( EV_FindTargets,            idEntity::Event_FindTargets )
  130.     EVENT( EV_ActivateTargets,        idEntity::Event_ActivateTargets )
  131.     EVENT( EV_NumTargets,            idEntity::Event_NumTargets )
  132.     EVENT( EV_GetTarget,            idEntity::Event_GetTarget )
  133.     EVENT( EV_RandomTarget,            idEntity::Event_RandomTarget )
  134.     EVENT( EV_BindToJoint,            idEntity::Event_BindToJoint )
  135.     EVENT( EV_RemoveBinds,            idEntity::Event_RemoveBinds )
  136.     EVENT( EV_Bind,                    idEntity::Event_Bind )
  137.     EVENT( EV_BindPosition,            idEntity::Event_BindPosition )
  138.     EVENT( EV_Unbind,                idEntity::Event_Unbind )
  139.     EVENT( EV_SpawnBind,            idEntity::Event_SpawnBind )
  140.     EVENT( EV_SetOwner,                idEntity::Event_SetOwner )
  141.     EVENT( EV_SetModel,                idEntity::Event_SetModel )
  142.     EVENT( EV_SetSkin,                idEntity::Event_SetSkin )
  143.     EVENT( EV_GetShaderParm,        idEntity::Event_GetShaderParm )
  144.     EVENT( EV_SetShaderParm,        idEntity::Event_SetShaderParm )
  145.     EVENT( EV_SetShaderParms,        idEntity::Event_SetShaderParms )
  146.     EVENT( EV_SetColor,                idEntity::Event_SetColor )
  147.     EVENT( EV_GetColor,                idEntity::Event_GetColor )
  148.     EVENT( EV_IsHidden,                idEntity::Event_IsHidden )
  149.     EVENT( EV_Hide,                    idEntity::Event_Hide )
  150.     EVENT( EV_Show,                    idEntity::Event_Show )
  151.     EVENT( EV_CacheSoundShader,        idEntity::Event_CacheSoundShader )
  152.     EVENT( EV_StartSoundShader,        idEntity::Event_StartSoundShader )
  153.     EVENT( EV_StartSound,            idEntity::Event_StartSound )
  154.     EVENT( EV_StopSound,            idEntity::Event_StopSound )
  155.     EVENT( EV_FadeSound,            idEntity::Event_FadeSound )
  156.     EVENT( EV_GetWorldOrigin,        idEntity::Event_GetWorldOrigin )
  157.     EVENT( EV_SetWorldOrigin,        idEntity::Event_SetWorldOrigin )
  158.     EVENT( EV_GetOrigin,            idEntity::Event_GetOrigin )
  159.     EVENT( EV_SetOrigin,            idEntity::Event_SetOrigin )
  160.     EVENT( EV_GetAngles,            idEntity::Event_GetAngles )
  161.     EVENT( EV_SetAngles,            idEntity::Event_SetAngles )
  162.     EVENT( EV_GetLinearVelocity,    idEntity::Event_GetLinearVelocity )
  163.     EVENT( EV_SetLinearVelocity,    idEntity::Event_SetLinearVelocity )
  164.     EVENT( EV_GetAngularVelocity,    idEntity::Event_GetAngularVelocity )
  165.     EVENT( EV_SetAngularVelocity,    idEntity::Event_SetAngularVelocity )
  166.     EVENT( EV_GetSize,                idEntity::Event_GetSize )
  167.     EVENT( EV_SetSize,                idEntity::Event_SetSize )
  168.     EVENT( EV_GetMins,                idEntity::Event_GetMins)
  169.     EVENT( EV_GetMaxs,                idEntity::Event_GetMaxs )
  170.     EVENT( EV_Touches,                idEntity::Event_Touches )
  171.     EVENT( EV_SetGuiParm,             idEntity::Event_SetGuiParm )
  172.     EVENT( EV_SetGuiFloat,             idEntity::Event_SetGuiFloat )
  173.     EVENT( EV_GetNextKey,            idEntity::Event_GetNextKey )
  174.     EVENT( EV_SetKey,                idEntity::Event_SetKey )
  175.     EVENT( EV_GetKey,                idEntity::Event_GetKey )
  176.     EVENT( EV_GetIntKey,            idEntity::Event_GetIntKey )
  177.     EVENT( EV_GetFloatKey,            idEntity::Event_GetFloatKey )
  178.     EVENT( EV_GetVectorKey,            idEntity::Event_GetVectorKey )
  179.     EVENT( EV_GetEntityKey,            idEntity::Event_GetEntityKey )
  180.     EVENT( EV_RestorePosition,        idEntity::Event_RestorePosition )
  181.     EVENT( EV_UpdateCameraTarget,    idEntity::Event_UpdateCameraTarget )
  182.     EVENT( EV_DistanceTo,            idEntity::Event_DistanceTo )
  183.     EVENT( EV_DistanceToPoint,        idEntity::Event_DistanceToPoint )
  184.     EVENT( EV_StartFx,                idEntity::Event_StartFx )
  185.     EVENT( EV_Thread_WaitFrame,        idEntity::Event_WaitFrame )
  186.     EVENT( EV_Thread_Wait,            idEntity::Event_Wait )
  187.     EVENT( EV_HasFunction,            idEntity::Event_HasFunction )
  188.     EVENT( EV_CallFunction,            idEntity::Event_CallFunction )
  189.     EVENT( EV_SetNeverDormant,        idEntity::Event_SetNeverDormant )
  190.  
  191. // RAVEN BEGIN
  192. // bgeisler: go back to default skin
  193.     EVENT( EV_ClearSkin,            idEntity::Event_ClearSkin )
  194. // kfuller: added events
  195.     EVENT( EV_SetContents,            idEntity::Event_SetContents )
  196.     EVENT( EV_GetLastBlocker,        idEntity::Event_GetLastBlocker)
  197. // bdube: effect events
  198.     EVENT( EV_PlayEffect,            idEntity::Event_PlayEffect )
  199.     EVENT( EV_StopEffect,            idEntity::Event_StopEffect )
  200.     EVENT( EV_StopAllEffects,        idEntity::Event_StopAllEffects )
  201.     EVENT( EV_GetHealth,            idEntity::Event_GetHealth )
  202. // bdube: mesh events
  203.     EVENT( EV_HideSurface,            idEntity::Event_HideSurface )
  204.     EVENT( EV_ShowSurface,            idEntity::Event_ShowSurface )
  205. // bdube: gui events
  206.     EVENT( EV_GuiEvent,                idEntity::Event_GuiEvent )
  207. // jscott: playback callback
  208.     EVENT( EV_PlaybackCallback,        idEntity::Event_PlaybackCallback )
  209. // nmckenzie: Check who we're bound to.
  210.     EVENT( EV_GetBindMaster,        idEntity::Event_GetBindMaster )
  211.     EVENT( EV_ApplyImpulse,            idEntity::Event_ApplyImpulse )
  212. // abahr: so we can call this from script
  213.     EVENT( EV_RemoveNullTargets,    idEntity::Event_RemoveNullTargets )
  214.     EVENT( EV_IsA,                    idEntity::Event_IsA )
  215.     EVENT( EV_IsSameTypeAs,            idEntity::Event_IsSameTypeAs )
  216.     EVENT( EV_MatchPrefix,            idEntity::Event_MatchPrefix )
  217.     EVENT( EV_ClearTargetList,        idEntity::Event_ClearTargetList )
  218. // twhitaker: to dynamically add/remove targets in script
  219.     EVENT( EV_AppendTarget,            idEntity::Event_AppendTarget )
  220.     EVENT( EV_RemoveTarget,            idEntity::Event_RemoveTarget )
  221. // mekberg: added
  222.     EVENT( EV_SetHealth,            idEntity::Event_SetHealth )
  223. // RAVEN END
  224. END_CLASS
  225.  
  226. /*
  227. ================
  228. UpdateGuiParms
  229. ================
  230. */
  231. void UpdateGuiParms( idUserInterface *gui, const idDict *args ) {
  232.     if ( gui == NULL || args == NULL ) {
  233.         return;
  234.     }
  235.     const idKeyValue *kv = args->MatchPrefix( "gui_parm", NULL );
  236.     while( kv ) {
  237.         gui->SetStateString( kv->GetKey(), common->GetLocalizedString( kv->GetValue() ) );
  238.         kv = args->MatchPrefix( "gui_parm", kv );
  239.     }
  240.     gui->SetStateBool( "noninteractive",  args->GetBool( "gui_noninteractive" ) ) ;
  241.     gui->StateChanged( gameLocal.time );
  242. }
  243.  
  244. /*
  245. ================
  246. AddRenderGui
  247. ================
  248. */
  249. void AddRenderGui( const char *name, idUserInterface **gui, const idDict *args ) {
  250.  
  251.     const idKeyValue *kv = args->MatchPrefix( "gui_parm", NULL );
  252.     *gui = uiManager->FindGui( name, true, ( kv != NULL ) || args->GetBool( "gui_noninteractive" ) );
  253.     UpdateGuiParms( *gui, args );
  254. }
  255.  
  256. /*
  257. ================
  258. idGameEdit::ParseSpawnArgsToRenderEntity
  259.  
  260. parse the static model parameters
  261. this is the canonical renderEntity parm parsing,
  262. which should be used by dmap and the editor
  263. ================
  264. */
  265. void idGameEdit::ParseSpawnArgsToRenderEntity( const idDict *args, renderEntity_t *renderEntity ) {
  266.     int            i;
  267.     const char    *temp;
  268.     idVec3        color;
  269.     float        angle;
  270.     const idDeclModelDef *modelDef;
  271.  
  272.     memset( renderEntity, 0, sizeof( *renderEntity ) );
  273.  
  274.     temp = args->GetString( "model" );
  275.  
  276.     modelDef = NULL;
  277.     if ( temp[0] != '\0' ) {
  278.         if ( !strstr( temp, "." ) ) {
  279.             modelDef = static_cast<const idDeclModelDef *>( declManager->FindType( DECL_MODELDEF, temp, false ) );
  280.             if ( modelDef ) {
  281.                 renderEntity->hModel = modelDef->ModelHandle();
  282.                 if ( renderEntity->hModel && !renderEntity->hModel->IsLoaded() ) {
  283.                     renderEntity->hModel->LoadModel();
  284.                 }
  285.             }
  286.         }
  287.  
  288.         if ( !renderEntity->hModel ) {
  289.             renderEntity->hModel = renderModelManager->FindModel( temp );
  290.         }
  291.     }
  292.     if ( renderEntity->hModel ) {
  293.         renderEntity->bounds = renderEntity->hModel->Bounds( renderEntity );
  294.     } else {
  295.         renderEntity->bounds.Zero();
  296.     }
  297.  
  298.     temp = args->GetString( "skin" );
  299.     if ( temp[0] != '\0' ) {
  300.         renderEntity->customSkin = declManager->FindSkin( temp );
  301.     } else if ( modelDef ) {
  302.         renderEntity->customSkin = modelDef->GetDefaultSkin();
  303.     }
  304.  
  305.     temp = args->GetString( "shader" );
  306.     if ( temp[0] != '\0' ) {
  307.         renderEntity->customShader = declManager->FindMaterial( temp );
  308.     }        
  309.  
  310.     args->GetVector( "origin", "0 0 0", renderEntity->origin );
  311.  
  312.     // get the rotation matrix in either full form, or single angle form
  313.     if ( !args->GetMatrix( "rotation", "1 0 0 0 1 0 0 0 1", renderEntity->axis ) ) {
  314.         angle = args->GetFloat( "angle" );
  315. // RAVEN BEGIN
  316. // abahr: allowing up and down buttons to affect orientation
  317.         if( angle == -1.0f ) {
  318.             renderEntity->axis = idAngles( -90.0f, 0.0f, 0.0f ).ToMat3();
  319.         } else if( angle == -2.0f ) {
  320.             renderEntity->axis = idAngles( 90.0f, 0.0f, 0.0f ).ToMat3();
  321.         } else
  322. // RAVEN END
  323.         if ( angle != 0.0f ) {
  324.             renderEntity->axis = idAngles( 0.0f, angle, 0.0f ).ToMat3();
  325.         } else {
  326.             renderEntity->axis.Identity();
  327.         }
  328.     }
  329.  
  330. // RAVEN BEGIN
  331.     renderEntity->referenceSoundHandle = -1;
  332. // RAVEN END
  333.  
  334.     // get shader parms
  335.     args->GetVector( "_color", "1 1 1", color );
  336.     renderEntity->shaderParms[ SHADERPARM_RED ]        = color[0];
  337.     renderEntity->shaderParms[ SHADERPARM_GREEN ]    = color[1];
  338.     renderEntity->shaderParms[ SHADERPARM_BLUE ]    = color[2];
  339.     renderEntity->shaderParms[ 3 ]                    = args->GetFloat( "shaderParm3", "1" );
  340.     renderEntity->shaderParms[ 4 ]                    = args->GetFloat( "shaderParm4", "0" );
  341.     renderEntity->shaderParms[ 5 ]                    = args->GetFloat( "shaderParm5", "0" );
  342.     renderEntity->shaderParms[ 6 ]                    = args->GetFloat( "shaderParm6", "0" );
  343.     renderEntity->shaderParms[ 7 ]                    = args->GetFloat( "shaderParm7", "0" );
  344.     renderEntity->shaderParms[ 8 ]                    = args->GetFloat( "shaderParm8", "0" );
  345.     renderEntity->shaderParms[ 9 ]                    = args->GetFloat( "shaderParm9", "0" );
  346.     renderEntity->shaderParms[ 10 ]                    = args->GetFloat( "shaderParm10", "0" );
  347.     renderEntity->shaderParms[ 11 ]                    = args->GetFloat( "shaderParm11", "0" );
  348.  
  349.     // check noDynamicInteractions flag
  350.     renderEntity->noDynamicInteractions = args->GetBool( "noDynamicInteractions" );
  351.  
  352.     // check noshadows flag
  353.     renderEntity->noShadow = args->GetBool( "noshadows" );
  354.  
  355.     // check noselfshadows flag
  356.     renderEntity->noSelfShadow = args->GetBool( "noselfshadows" );
  357.  
  358.     // init any guis, including entity-specific states
  359.     for( i = 0; i < MAX_RENDERENTITY_GUI; i++ ) {
  360.         temp = args->GetString( i == 0 ? "gui" : va( "gui%d", i + 1 ) );
  361.         if ( temp[ 0 ] != '\0' ) {
  362.             AddRenderGui( temp, &renderEntity->gui[ i ], args );
  363.         }
  364.     }
  365. }
  366.  
  367. /*
  368. ================
  369. idGameEdit::ParseSpawnArgsToRefSound
  370.  
  371. parse the sound parameters
  372. this is the canonical refSound parm parsing,
  373. which should be used by dmap and the editor
  374. ================
  375. */
  376. void idGameEdit::ParseSpawnArgsToRefSound( const idDict *args, refSound_t *refSound ) {
  377.     const char    *temp;
  378.  
  379.     memset( refSound, 0, sizeof( *refSound ) );
  380.     refSound->referenceSoundHandle = -1;
  381.  
  382. // RAVEN BEGIN
  383.     refSound->parms.minDistance = args->GetFloat( "s_mindistance" );
  384.     refSound->parms.maxDistance = args->GetFloat( "s_maxdistance" );
  385.     // WARNING: This overrides the volume; it does not modify it
  386.     if( args->GetFloat( "s_volume" ) != 0.0f ) {
  387.         refSound->parms.volume = idMath::dBToScale( args->GetFloat( "s_volume" ) );
  388.     }
  389.  
  390.     if( refSound->parms.volume < 0.0f || refSound->parms.volume > 5.0f ) {
  391.         common->Warning( "Unreasonable volume (%g) on entity \'%s\'", refSound->parms.volume, args->GetString( "name" ) );
  392.         refSound->parms.volume = 5.0f;
  393.     }
  394. // RAVEN END
  395.     refSound->parms.shakes = args->GetFloat( "s_shakes" );
  396.  
  397.     args->GetVector( "origin", "0 0 0", refSound->origin );
  398.  
  399.     // if a diversity is not specified, every sound start will make
  400.     // a random one.  Specifying diversity is usefull to make multiple
  401.     // lights all share the same buzz sound offset, for instance.
  402.     refSound->diversity = args->GetFloat( "s_diversity", "-1" );
  403.     refSound->waitfortrigger = args->GetBool( "s_waitfortrigger" );
  404.  
  405.     if ( args->GetBool( "s_omni" ) ) {
  406.         refSound->parms.soundShaderFlags |= SSF_OMNIDIRECTIONAL;
  407.     }
  408.     if ( args->GetBool( "s_looping" ) ) {
  409.         refSound->parms.soundShaderFlags |= SSF_LOOPING;
  410.     }
  411.     if ( args->GetBool( "s_occlusion" ) ) {
  412.         refSound->parms.soundShaderFlags |= SSF_NO_OCCLUSION;
  413.     }
  414.     if ( args->GetBool( "s_global" ) ) {
  415.         refSound->parms.soundShaderFlags |= SSF_GLOBAL;
  416.     }
  417.     if ( args->GetBool( "s_unclamped" ) ) {
  418.         refSound->parms.soundShaderFlags |= SSF_UNCLAMPED;
  419.     }
  420.  
  421.     refSound->parms.soundClass = args->GetInt( "s_soundClass" );
  422.  
  423.     temp = args->GetString( "s_shader" );
  424.     if ( temp[0] != '\0' ) {
  425.         refSound->shader = declManager->FindSound( temp );
  426.     }
  427.  
  428. // RAVEN BEGIN
  429.     if( refSound->parms.maxDistance < refSound->parms.minDistance ) {
  430.         common->Warning( "ParseSpawnArgsToRefSound: Max distance less than min distance for entity \'%s\'", args->GetString( "name", "*unknown*" ) );
  431.     }
  432. // RAVEN END
  433. }
  434.  
  435. /*
  436. ===============
  437. idEntity::UpdateChangeableSpawnArgs
  438.  
  439. Any key val pair that might change during the course of the game ( via a gui or whatever )
  440. should be initialize here so a gui or other trigger can change something and have it updated
  441. properly. An optional source may be provided if the values reside in an outside dictionary and
  442. first need copied over to spawnArgs
  443. ===============
  444. */
  445. void idEntity::UpdateChangeableSpawnArgs( const idDict *source ) {
  446.     int i;
  447.     const char *target;
  448.  
  449.     if ( !source ) {
  450.         source = &spawnArgs;
  451.     }
  452.     cameraTarget = NULL;
  453.     target = source->GetString( "cameraTarget" );
  454.     if ( target && target[0] ) {
  455. // RAVEN BEGIN
  456. // bdube: EV_UpdateCameraTarget pulls from spawnargs so we need to move the target over
  457.         spawnArgs.Set ( "cameraTarget", target );
  458. // RAVEN END        
  459.         // update the camera taget
  460.         PostEventMS( &EV_UpdateCameraTarget, 0 );
  461.     }
  462.  
  463.     for ( i = 0; i < MAX_RENDERENTITY_GUI; i++ ) {
  464.         UpdateGuiParms( renderEntity.gui[ i ], source );
  465.     }
  466. }
  467.  
  468. /*
  469. ================
  470. idEntity::idEntity
  471. ================
  472. */
  473. idEntity::idEntity() {
  474.  
  475.     entityNumber    = ENTITYNUM_NONE;
  476.     entityDefNumber = -1;
  477.  
  478.     spawnNode.SetOwner( this );
  479.     activeNode.SetOwner( this );
  480.  
  481.     snapshotNode.SetOwner( this );
  482.     snapshotSequence = -1;
  483.     snapshotBits = 0;
  484.  
  485.     thinkFlags        = 0;
  486.     dormantStart    = 0;
  487.     cinematic        = false;
  488.     renderView        = NULL;
  489.     cameraTarget    = NULL;
  490.     health            = 0;
  491.  
  492.     physics            = NULL;
  493.     bindMaster        = NULL;
  494.     bindJoint        = INVALID_JOINT;
  495.     bindBody        = -1;
  496.     teamMaster        = NULL;
  497.     teamChain        = NULL;
  498.     signals            = NULL;
  499.  
  500.     memset( PVSAreas, 0, sizeof( PVSAreas ) );
  501.     numPVSAreas        = -1;
  502.  
  503.     memset( &fl, 0, sizeof( fl ) );
  504.     fl.neverDormant    = true;            // most entities never go dormant
  505.  
  506.     memset( &renderEntity, 0, sizeof( renderEntity ) );
  507.     modelDefHandle    = -1;
  508.     memset( &refSound, 0, sizeof( refSound ) );
  509.     refSound.referenceSoundHandle = -1;
  510.  
  511.     mpGUIState = -1;
  512.  
  513. // RAVEN BEGIN
  514. // rjohnson: added this to persist long thinking entities
  515.     mLastLongThinkTime = 0;
  516.     mLastLongThinkColor.Zero();
  517. // ddynerman: instance, clipworld
  518.     SetInstance( 0 );
  519.     SetClipWorld( 0 );
  520.     fl.persistAcrossInstances = false;
  521. // twhitaker
  522.     forwardDamageEnt = NULL;
  523. // ddynerman: optional preprediction
  524.     predictTime = 0;
  525. // RAVEN END
  526. }
  527.  
  528. /*
  529. ================
  530. idEntity::Spawn
  531. ================
  532. */
  533. void idEntity::Spawn( void ) {
  534.     int                    i;
  535.     const char            *temp;
  536.     idVec3                origin;
  537.     idMat3                axis;
  538.     const idKeyValue    *networkSync;
  539.     const char            *classname;
  540.     const char            *scriptObjectName;
  541.  
  542.     gameLocal.RegisterEntity( this );
  543.  
  544. // RAVEN BEGIN
  545. // mwhitlock: Xenon texture streaming
  546. #if defined(_XENON)
  547.     declManager->SetEntityMaterialList(&renderEntity.allMaterials);
  548. #endif
  549.  
  550. // bdube: make sure there is a classname before trying to use it
  551.     if ( spawnArgs.GetString( "classname", NULL, &classname ) ) {
  552.         const idDeclEntityDef *def = gameLocal.FindEntityDef( classname, false );
  553.         if ( def ) {
  554.             entityDefNumber = def->Index();
  555.         }
  556.     }
  557.  
  558.     // Persona is a set of keys that augment an entity giving it its own custom persona
  559.     const idDict* dict;
  560.     dict = gameLocal.FindEntityDefDict ( spawnArgs.GetString ( "def_persona", "" ), false );
  561.     if ( dict ) {
  562.         spawnArgs.Copy ( *dict );
  563.     }
  564. // RAVEN END
  565.  
  566.     // parse static models the same way the editor display does
  567.     gameEdit->ParseSpawnArgsToRenderEntity( &spawnArgs, &renderEntity );
  568.  
  569. // RAVEN BEGIN
  570. // bdube: added hidesurface
  571.     const idKeyValue* kv;
  572.     for ( kv = spawnArgs.MatchPrefix ( "hidesurface", NULL );
  573.           kv;
  574.           kv = spawnArgs.MatchPrefix ( "hidesurface", kv ) ) {
  575.         HideSurface ( kv->GetValue() );
  576.     }
  577. // RAVEN END        
  578.  
  579.     renderEntity.entityNum = entityNumber;
  580.  
  581. // RAVEN BEGIN
  582. // ddynerman: LOD code
  583.     renderEntity.shadowLODDistance = spawnArgs.GetFloat( "shadow_lod_distance", "768.0" );
  584.     renderEntity.shadowLODDistance *= renderEntity.shadowLODDistance;
  585. // ddynerman: multiple clip worlds
  586.     int spawnInstance = spawnArgs.GetInt( "instance" );
  587.     SetInstance( spawnInstance );
  588. // RAVEN END
  589.  
  590.     // go dormant within 5 frames so that when the map starts most monsters are dormant
  591.     dormantStart = gameLocal.time - DELAY_DORMANT_TIME + gameLocal.msec * 5;
  592.  
  593.     origin = renderEntity.origin;
  594.     axis = renderEntity.axis;
  595.  
  596.     // do the audio parsing the same way dmap and the editor do
  597.     gameEdit->ParseSpawnArgsToRefSound( &spawnArgs, &refSound );
  598.  
  599.     // only play SCHANNEL_PRIVATE when sndworld->PlaceListener() is called with this listenerId
  600.     // don't spatialize sounds from the same entity
  601.     refSound.listenerId = entityNumber + 1;
  602.  
  603.     cameraTarget = NULL;
  604.     temp = spawnArgs.GetString( "cameraTarget" );
  605.     if ( temp && temp[0] ) {
  606.         // update the camera taget
  607.         PostEventMS( &EV_UpdateCameraTarget, 0 );
  608.     }
  609.  
  610.     for ( i = 0; i < MAX_RENDERENTITY_GUI; i++ ) {
  611.         UpdateGuiParms( renderEntity.gui[ i ], &spawnArgs );
  612.     }
  613.  
  614.     fl.solidForTeam = spawnArgs.GetBool( "solidForTeam", "0" );
  615. // RAVEN BEGIN
  616. // bdube: usable
  617.     fl.usable = spawnArgs.GetBool ( "usable", "0" );
  618. // RAVEN END
  619.  
  620.     fl.neverDormant = spawnArgs.GetBool( "neverDormant", "0" );
  621.     fl.hidden = spawnArgs.GetBool( "hide", "0" );
  622.     if ( fl.hidden ) {
  623.         // make sure we're hidden, since a spawn function might not set it up right
  624.         PostEventMS( &EV_Hide, 0 );
  625.     }
  626.     cinematic = spawnArgs.GetBool( "cinematic", "0" );
  627.  
  628.     networkSync = spawnArgs.FindKey( "networkSync" );
  629.     if ( networkSync ) {
  630.         fl.networkSync = ( atoi( networkSync->GetValue() ) != 0 );
  631.     }
  632.  
  633.     // every object will have a unique name
  634.     temp = spawnArgs.GetString( "name", va( "%s_%s_%d", GetClassname(), spawnArgs.GetString( "classname" ), entityNumber ) );
  635.     SetName( temp );
  636.  
  637.     // if we have targets, wait until all entities are spawned to get them
  638.     if ( spawnArgs.MatchPrefix( "target" ) || spawnArgs.MatchPrefix( "guiTarget" ) ) {
  639.         if ( gameLocal.GameState() == GAMESTATE_STARTUP ) {
  640.             PostEventMS( &EV_FindTargets, 0 );
  641.         } else {
  642.             // not during spawn, so it's ok to get the targets
  643.             FindTargets();
  644.         }
  645.     }
  646.  
  647.     health = spawnArgs.GetInt( "health" );
  648.  
  649.     InitDefaultPhysics( origin, axis );
  650.  
  651.     SetOrigin( origin );
  652.     SetAxis( axis );
  653.  
  654.     temp = spawnArgs.GetString( "model" );
  655.     if ( temp && *temp ) {
  656.         SetModel( temp );
  657.     }
  658.  
  659.     if ( spawnArgs.GetString( "bind", "", &temp ) ) {
  660.         PostEventMS( &EV_SpawnBind, 0 );
  661.     }
  662.  
  663.     // auto-start a sound on the entity
  664.     if ( refSound.shader && !refSound.waitfortrigger ) {
  665.         StartSoundShader( refSound.shader, SND_CHANNEL_ANY, 0, false, NULL );
  666.     }
  667.  
  668.     // setup script object
  669.     if ( ShouldConstructScriptObjectAtSpawn() && spawnArgs.GetString( "scriptobject", NULL, &scriptObjectName ) ) {
  670.         if ( !scriptObject.SetType( scriptObjectName ) ) {
  671.             gameLocal.Error( "Script object '%s' not found on entity '%s'.", scriptObjectName, name.c_str() );
  672.         }
  673.  
  674.         ConstructScriptObject();
  675.     }
  676.  
  677. // RAVEN BEGIN
  678.     fl.persistAcrossInstances = false;
  679. // bgeisler: added
  680.     fl.triggerAnim = spawnArgs.GetBool( "trigger_anim" );
  681.  
  682. // mwhitlock: Xenon texture streaming
  683. #if defined(_XENON)
  684.     declManager->SetEntityMaterialList(0);
  685. #endif
  686. // RAVEN END
  687. }
  688.  
  689. /*
  690. ================
  691. idEntity::~idEntity
  692. ================
  693. */
  694. idEntity::~idEntity( void ) {
  695.     DeconstructScriptObject();
  696.     scriptObject.Free();
  697.  
  698.     if ( thinkFlags ) {
  699.         BecomeInactive( thinkFlags );
  700.     }
  701.     activeNode.Remove();
  702.  
  703.     Signal( SIG_REMOVED );
  704.  
  705.     // we have to set back the default physics object before unbinding because the entity
  706.     // specific physics object might be an entity variable and as such could already be destroyed.
  707.     SetPhysics( NULL );
  708.  
  709.     // remove any entities that are bound to me
  710.     RemoveBinds();
  711.  
  712.     // unbind from master
  713.     Unbind();
  714.     QuitTeam();
  715.  
  716.     gameLocal.RemoveEntityFromHash( name.c_str(), this );
  717.  
  718.     delete renderView;
  719.     renderView = NULL;
  720.  
  721.     delete signals;
  722.     signals = NULL;
  723.  
  724. // RAVEN BEGIN
  725. // bdube: make sure all sounds and attached effects are stopped
  726.     StopSound( SCHANNEL_ANY, false );
  727.     
  728.     RemoveClientEntities();
  729. // RAVEN END
  730.  
  731.     FreeModelDef();
  732.     FreeSoundEmitter( false );
  733.  
  734.     gameLocal.UnregisterEntity( this );
  735. }
  736.  
  737. /*
  738. ================
  739. idEntity::Save
  740. ================
  741. */
  742. void idEntity::Save( idSaveGame *savefile ) const {
  743.     int                i, j;
  744.     rvClientEntity* cent;
  745.  
  746.     savefile->WriteInt( entityNumber );
  747.     savefile->WriteInt( entityDefNumber );
  748.  
  749.     // spawnNode and activeNode are restored by gameLocal
  750.  
  751.     // idLinkList<idEntity>    snapshotNode;
  752.  
  753.     savefile->WriteInt( snapshotSequence );
  754.     savefile->WriteInt( snapshotBits );
  755.  
  756.     savefile->WriteString( name );
  757.     savefile->WriteDict( &spawnArgs );
  758.     scriptObject.Save( savefile );
  759.  
  760.     savefile->WriteInt( thinkFlags );
  761.     savefile->WriteInt( dormantStart );
  762.     savefile->WriteBool( cinematic );
  763.  
  764.     // renderView_t * renderView;
  765.  
  766.     savefile->WriteObject( cameraTarget );
  767.  
  768.     savefile->WriteInt( targets.Num() );
  769.     for( i = 0; i < targets.Num(); i++ ) {
  770.         targets[ i ].Save( savefile );
  771.     }
  772.  
  773.     savefile->WriteInt( health );
  774.  
  775.     savefile->WriteInt( clientEntities.Num() );
  776.     for( cent = clientEntities.Next(); cent; cent = cent->bindNode.Next() ) {
  777.         savefile->WriteObject( cent );
  778.     }
  779.  
  780. //    savefile->WriteInt( mLastLongThinkTime );            // Debug vars - don't save
  781. //    savefile->WriteVec4( mLastLongThinkColor );            // Debug vars - don't save
  782.  
  783.     savefile->Write( &fl, sizeof( fl ) );
  784.  
  785.     savefile->WriteRenderEntity( renderEntity );
  786.     savefile->WriteInt( modelDefHandle );
  787.     savefile->WriteRefSound( refSound );
  788.  
  789. // RAVEN BEGIN
  790. // mekberg: proper save
  791.     forwardDamageEnt.Save ( savefile );
  792. // RAVEN END
  793.  
  794.     savefile->WriteStaticObject( defaultPhysicsObj );
  795.  
  796.     savefile->WriteObject( bindMaster );
  797.     savefile->WriteJoint( bindJoint );
  798.     savefile->WriteInt( bindBody );
  799.     savefile->WriteObject( teamMaster );
  800.     savefile->WriteObject( teamChain );
  801.  
  802.     savefile->WriteInt( numPVSAreas );
  803.     for( i = 0; i < MAX_PVS_AREAS; i++ ) {
  804.         savefile->WriteInt( PVSAreas[ i ] );
  805.     }
  806.  
  807.     if ( !signals ) {
  808.         savefile->WriteBool( false );
  809.     } else {
  810.         savefile->WriteBool( true );
  811.         for( i = 0; i < NUM_SIGNALS; i++ ) {
  812.             savefile->WriteInt( signals->signal[ i ].Num() );
  813.             for( j = 0; j < signals->signal[ i ].Num(); j++ ) {
  814.                 savefile->WriteInt( signals->signal[ i ][ j ].threadnum );
  815.                 savefile->WriteString( signals->signal[ i ][ j ].function->Name() );
  816.             }
  817.         }
  818.     }
  819.  
  820.     savefile->WriteInt( mpGUIState );
  821.  
  822.     savefile->WriteInt( instance );
  823.     savefile->WriteInt( clipWorld );
  824. }
  825.  
  826. /*
  827. ================
  828. idEntity::Restore
  829. ================
  830. */
  831. void idEntity::Restore( idRestoreGame *savefile ) {
  832.     int                i, j;
  833.     int                num;
  834.     rvClientEntity    *temp;
  835.     idStr            funcname;
  836.  
  837.     savefile->ReadInt( entityNumber );
  838.     savefile->ReadInt( entityDefNumber );
  839.  
  840.     // spawnNode and activeNode are restored by gameLocal
  841.  
  842.     // idLinkList<idEntity>    snapshotNode; 
  843.  
  844.     savefile->ReadInt( snapshotSequence );
  845.     savefile->ReadInt( snapshotBits );
  846.  
  847.     savefile->ReadString( name );
  848.     SetName( name );
  849.     savefile->ReadDict( &spawnArgs );
  850.  
  851.     scriptObject.Restore( savefile );
  852.  
  853.     savefile->ReadInt( thinkFlags );
  854.     savefile->ReadInt( dormantStart );
  855.     savefile->ReadBool( cinematic );
  856.  
  857.     // renderView_t *            renderView;
  858.  
  859.     savefile->ReadObject( reinterpret_cast<idClass *&>( cameraTarget ) );
  860.  
  861.     targets.Clear();
  862.     savefile->ReadInt( num );
  863.     targets.SetNum( num );
  864.     for( i = 0; i < num; i++ ) {
  865.         targets[ i ].Restore( savefile );
  866.     }
  867.  
  868.     savefile->ReadInt( health );
  869.  
  870.     savefile->ReadInt( num );
  871.     for( i = 0; i < num; i++ ) {
  872.         savefile->ReadObject( reinterpret_cast<idClass *&>( temp ) );
  873.         if( temp ) {
  874.             temp->bindNode.AddToEnd( clientEntities );
  875.         }
  876.     }
  877.  
  878. //    savefile->ReadInt( mLastLongThinkTime );            // Debug vars - don't save
  879. //    savefile->ReadVec4( mLastLongThinkColor );            // Debug vars - don't save
  880.  
  881.     savefile->Read( &fl, sizeof( fl ) );
  882.  
  883. // RAVEN BEGIN
  884.     savefile->ReadRenderEntity( renderEntity, &spawnArgs );
  885. // RAVEN END
  886.     savefile->ReadInt( modelDefHandle );
  887.     savefile->ReadRefSound( refSound );
  888.     
  889. // RAVEN BEGIN
  890. // mekberg: proper restore
  891.     forwardDamageEnt.Restore ( savefile );
  892. // RAVEN END
  893.  
  894.     savefile->ReadStaticObject( defaultPhysicsObj );
  895.     RestorePhysics( &defaultPhysicsObj );
  896.  
  897.     savefile->ReadObject( reinterpret_cast<idClass *&>( bindMaster ) );
  898.     savefile->ReadJoint( bindJoint );
  899.     savefile->ReadInt( bindBody );
  900.     savefile->ReadObject( reinterpret_cast<idClass *&>( teamMaster ) );
  901.     savefile->ReadObject( reinterpret_cast<idClass *&>( teamChain ) );
  902.  
  903.     savefile->ReadInt( numPVSAreas );
  904.     for( i = 0; i < MAX_PVS_AREAS; i++ ) {
  905.         savefile->ReadInt( PVSAreas[ i ] );
  906.     }
  907.  
  908.     bool readsignals;
  909.     savefile->ReadBool( readsignals );
  910.     if ( readsignals ) {
  911.         signals = new signalList_t;
  912.         for( i = 0; i < NUM_SIGNALS; i++ ) {
  913.             savefile->ReadInt( num );
  914.             signals->signal[ i ].SetNum( num );
  915.             for( j = 0; j < num; j++ ) {
  916.                 savefile->ReadInt( signals->signal[ i ][ j ].threadnum );
  917.                 savefile->ReadString( funcname );
  918.                 signals->signal[ i ][ j ].function = gameLocal.program.FindFunction( funcname );
  919.                 if ( !signals->signal[ i ][ j ].function ) {
  920.                     savefile->Error( "Function '%s' not found", funcname.c_str() );
  921.                 }
  922.             }
  923.         }
  924.     }
  925.  
  926.     savefile->ReadInt( mpGUIState );
  927.  
  928.     // restore must retrieve modelDefHandle from the renderer
  929.     if ( modelDefHandle != -1 ) {
  930.         modelDefHandle = gameRenderWorld->AddEntityDef( &renderEntity );
  931.     }
  932.  
  933.     savefile->ReadInt( instance );
  934.     savefile->ReadInt( clipWorld );
  935. }
  936.  
  937. /*
  938. ================
  939. idEntity::GetEntityDefName
  940. ================
  941. */
  942. const char * idEntity::GetEntityDefName( void ) const {
  943.     if ( entityDefNumber < 0 ) {
  944.         return "*unknown*";
  945.     }
  946.     return declManager->DeclByIndex( DECL_ENTITYDEF, entityDefNumber, false )->GetName();
  947. }
  948.  
  949. /*
  950. ================
  951. idEntity::SetName
  952. ================
  953. */
  954. void idEntity::SetName( const char *newname ) {
  955.     if ( name.Length() ) {
  956.         gameLocal.RemoveEntityFromHash( name.c_str(), this );
  957.         gameLocal.program.SetEntity( name, NULL );
  958.     }
  959.  
  960.     name = newname;
  961.     if ( name.Length() ) {
  962.         if ( ( name == "NULL" ) || ( name == "null_entity" ) ) {
  963.             gameLocal.Error( "Cannot name entity '%s'.  '%s' is reserved for script.", name.c_str(), name.c_str() );
  964.         }
  965.         gameLocal.AddEntityToHash( name.c_str(), this );
  966.         gameLocal.program.SetEntity( name, this );
  967.     }
  968. }
  969.  
  970. /*
  971. ================
  972. idEntity::GetName
  973. ================
  974. */
  975. const char * idEntity::GetName( void ) const {
  976.     return name.c_str();
  977. }
  978.  
  979.  
  980. /***********************************************************************
  981.  
  982.     Thinking
  983.     
  984. ***********************************************************************/
  985.  
  986. /*
  987. ================
  988. idEntity::Think
  989. ================
  990. */
  991. void idEntity::Think( void ) {
  992.     RunPhysics();
  993.     Present();
  994. }
  995.  
  996. /*
  997. ================
  998. idEntity::DoDormantTests
  999.  
  1000. Monsters and other expensive entities that are completely closed
  1001. off from the player can skip all of their work
  1002. ================
  1003. */
  1004. bool idEntity::DoDormantTests( void ) {
  1005.     // Never go dormant?
  1006.     if ( fl.neverDormant || (gameLocal.inCinematic && cinematic) ) {
  1007.         return false;
  1008.     }
  1009.  
  1010.     // if the monster area is not topologically connected to a player
  1011.     if ( !gameLocal.InPlayerConnectedArea( this ) ) {
  1012.         return true;
  1013.     } else {
  1014.         // the monster area is topologically connected to a player, but if
  1015.         // the monster hasn't been woken up before, do the more precise PVS check
  1016.         if ( !fl.hasAwakened ) {
  1017.             if ( !gameLocal.InPlayerPVS( this ) ) {
  1018.                 return true;
  1019.             }
  1020.         }
  1021.     }
  1022.     
  1023.     return false;
  1024. }
  1025.  
  1026. /*
  1027. ================
  1028. idEntity::CheckDormant
  1029.  
  1030. Monsters and other expensive entities that are completely closed
  1031. off from the player can skip all of their work
  1032. ================
  1033. */
  1034. bool idEntity::CheckDormant( void ) {
  1035.     bool dormant;
  1036.     
  1037.     dormant = DoDormantTests();
  1038.     if ( dormant ) {
  1039.         if ( dormantStart == 0 ) {
  1040.             dormantStart = gameLocal.time;
  1041.         }
  1042.         if ( gameLocal.time - dormantStart < DELAY_DORMANT_TIME ) {
  1043.             dormant = false;
  1044.         }
  1045.     } else {
  1046.         dormantStart = 0;
  1047.         fl.hasAwakened = true;
  1048.     }        
  1049.     
  1050.     if ( dormant && !fl.isDormant ) {
  1051.         fl.isDormant = true;
  1052.         DormantBegin();
  1053.     } else if ( !dormant && fl.isDormant ) {
  1054.         fl.isDormant = false;
  1055.         DormantEnd();
  1056.     }
  1057.  
  1058.     return dormant;
  1059. }
  1060.  
  1061. /*
  1062. ================
  1063. idEntity::DormantBegin
  1064.  
  1065. called when entity becomes dormant
  1066. ================
  1067. */
  1068. void idEntity::DormantBegin( void ) {
  1069. }
  1070.  
  1071. /*
  1072. ================
  1073. idEntity::DormantEnd
  1074.  
  1075. called when entity wakes from being dormant
  1076. ================
  1077. */
  1078. void idEntity::DormantEnd( void ) {
  1079. }
  1080.  
  1081. /*
  1082. ================
  1083. idEntity::IsActive
  1084. ================
  1085. */
  1086. bool idEntity::IsActive( void ) const {
  1087.     return activeNode.InList();
  1088. }
  1089.  
  1090. /*
  1091. ================
  1092. idEntity::BecomeActive
  1093. ================
  1094. */
  1095. void idEntity::BecomeActive( int flags ) {
  1096.     if ( ( flags & TH_PHYSICS ) ) {
  1097.         // enable the team master if this entity is part of a physics team
  1098.         if ( teamMaster && teamMaster != this ) {
  1099.             teamMaster->BecomeActive( TH_PHYSICS );
  1100.         } else if ( !( thinkFlags & TH_PHYSICS ) ) {
  1101.             // if this is a pusher
  1102. // RAVEN BEGIN
  1103. // jnewquist: Use accessor for static class type 
  1104.             if ( physics->IsType( idPhysics_Parametric::GetClassType() ) || physics->IsType( idPhysics_Actor::GetClassType() ) ) {
  1105. // RAVEN END
  1106.                 gameLocal.sortPushers = true;
  1107.             }
  1108. // RAVEN BEGIN
  1109. // abahr:
  1110. // jnewquist: Use accessor for static class type 
  1111.             if( physics->IsType( rvPhysics_Spline::GetClassType() ) ) {
  1112.                 gameLocal.sortPushers = true;
  1113.             }
  1114. // RAVEN END
  1115.         }
  1116.     }
  1117.  
  1118.     int oldFlags = thinkFlags;
  1119.     thinkFlags |= flags;
  1120.     if ( thinkFlags ) {
  1121.         if ( !IsActive() ) {
  1122.             activeNode.AddToEnd( gameLocal.activeEntities );
  1123.         } else if ( !oldFlags ) {
  1124.             // we became inactive this frame, so we have to decrease the count of entities to deactivate
  1125.             gameLocal.numEntitiesToDeactivate--;
  1126.         }
  1127.     }
  1128. }
  1129.  
  1130. /*
  1131. ================
  1132. idEntity::BecomeInactive
  1133. ================
  1134. */
  1135. void idEntity::BecomeInactive( int flags ) {
  1136.     if ( ( flags & TH_PHYSICS ) ) {
  1137.         // may only disable physics on a team master if no team members are running physics or bound to a joints
  1138.         if ( teamMaster == this ) {
  1139.             for ( idEntity *ent = teamMaster->teamChain; ent; ent = ent->teamChain ) {
  1140.                 if ( ( ent->thinkFlags & TH_PHYSICS ) || ( ( ent->bindMaster == this ) && ( ent->bindJoint != INVALID_JOINT ) ) ) {
  1141.                     flags &= ~TH_PHYSICS;
  1142.                     break;
  1143.                 }
  1144.             }
  1145.         }
  1146.     }
  1147.  
  1148.     if ( thinkFlags ) {
  1149.         thinkFlags &= ~flags;
  1150.         if ( !thinkFlags && IsActive() ) {
  1151.             gameLocal.numEntitiesToDeactivate++;
  1152.         }
  1153.     }
  1154.  
  1155.     if ( ( flags & TH_PHYSICS ) ) {
  1156.         // if this entity has a team master
  1157.         if ( teamMaster && teamMaster != this ) {
  1158.             // if the team master is at rest
  1159.             if ( teamMaster->IsAtRest() ) {
  1160.                 teamMaster->BecomeInactive( TH_PHYSICS );
  1161.             }
  1162.         }
  1163.     }
  1164. }
  1165.  
  1166. /***********************************************************************
  1167.  
  1168.     Visuals
  1169.     
  1170. ***********************************************************************/
  1171.  
  1172. /*
  1173. ================
  1174. idEntity::SetShaderParm
  1175. ================
  1176. */
  1177. void idEntity::SetShaderParm( int parmnum, float value ) {
  1178.     if ( ( parmnum < 0 ) || ( parmnum >= MAX_ENTITY_SHADER_PARMS ) ) {
  1179.         gameLocal.Warning( "shader parm index (%d) out of range", parmnum );
  1180.         return;
  1181.     }
  1182.  
  1183.     renderEntity.shaderParms[ parmnum ] = value;
  1184.     UpdateVisuals();
  1185. }
  1186.  
  1187. /*
  1188. ================
  1189. idEntity::SetColor
  1190. ================
  1191. */
  1192. void idEntity::SetColor( float red, float green, float blue ) {
  1193.     renderEntity.shaderParms[ SHADERPARM_RED ]        = red;
  1194.     renderEntity.shaderParms[ SHADERPARM_GREEN ]    = green;
  1195.     renderEntity.shaderParms[ SHADERPARM_BLUE ]        = blue;
  1196.     UpdateVisuals();
  1197. }
  1198.  
  1199. /*
  1200. ================
  1201. idEntity::SetColor
  1202. ================
  1203. */
  1204. void idEntity::SetColor( const idVec3 &color ) {
  1205.     SetColor( color[ 0 ], color[ 1 ], color[ 2 ] );
  1206.     UpdateVisuals();
  1207. }
  1208.  
  1209. /*
  1210. ================
  1211. idEntity::GetColor
  1212. ================
  1213. */
  1214. void idEntity::GetColor( idVec3 &out ) const {
  1215.     out[ 0 ] = renderEntity.shaderParms[ SHADERPARM_RED ];
  1216.     out[ 1 ] = renderEntity.shaderParms[ SHADERPARM_GREEN ];
  1217.     out[ 2 ] = renderEntity.shaderParms[ SHADERPARM_BLUE ];
  1218. }
  1219.  
  1220. /*
  1221. ================
  1222. idEntity::SetColor
  1223. ================
  1224. */
  1225. void idEntity::SetColor( const idVec4 &color ) {
  1226.     renderEntity.shaderParms[ SHADERPARM_RED ]        = color[ 0 ];
  1227.     renderEntity.shaderParms[ SHADERPARM_GREEN ]    = color[ 1 ];
  1228.     renderEntity.shaderParms[ SHADERPARM_BLUE ]        = color[ 2 ];
  1229.     renderEntity.shaderParms[ SHADERPARM_ALPHA ]    = color[ 3 ];
  1230.     UpdateVisuals();
  1231. }
  1232.  
  1233. /*
  1234. ================
  1235. idEntity::GetColor
  1236. ================
  1237. */
  1238. void idEntity::GetColor( idVec4 &out ) const {
  1239.     out[ 0 ] = renderEntity.shaderParms[ SHADERPARM_RED ];
  1240.     out[ 1 ] = renderEntity.shaderParms[ SHADERPARM_GREEN ];
  1241.     out[ 2 ] = renderEntity.shaderParms[ SHADERPARM_BLUE ];
  1242.     out[ 3 ] = renderEntity.shaderParms[ SHADERPARM_ALPHA ];
  1243. }
  1244.  
  1245. /*
  1246. ================
  1247. idEntity::UpdateAnimationControllers
  1248. ================
  1249. */
  1250. bool idEntity::UpdateAnimationControllers( void ) {
  1251.     // any ragdoll and IK animation controllers should be updated here
  1252.     return false;
  1253. }
  1254.  
  1255. /*
  1256. ================
  1257. idEntity::SetModel
  1258. ================
  1259. */
  1260. void idEntity::SetModel( const char *modelname ) {
  1261.     assert( modelname );
  1262.  
  1263.     FreeModelDef();
  1264.  
  1265.     renderEntity.hModel = renderModelManager->FindModel( modelname );
  1266.  
  1267.     if ( renderEntity.hModel ) {
  1268.         renderEntity.hModel->Reset();
  1269.     }
  1270.  
  1271.     renderEntity.callback = NULL;
  1272.     renderEntity.numJoints = 0;
  1273.     renderEntity.joints = NULL;
  1274.     if ( renderEntity.hModel ) {
  1275.         renderEntity.bounds = renderEntity.hModel->Bounds( &renderEntity );
  1276.     } else {
  1277.         renderEntity.bounds.Zero();
  1278.     }
  1279.  
  1280.     UpdateVisuals();
  1281. }
  1282.  
  1283. /*
  1284. ================
  1285. idEntity::SetSkin
  1286. ================
  1287. */
  1288. void idEntity::SetSkin( const idDeclSkin *skin ) {
  1289.     renderEntity.customSkin = skin;
  1290.     UpdateVisuals();
  1291. }
  1292. // RAVEN BEGIN
  1293. // bgeisler: go back to default skin
  1294. /*
  1295. ================
  1296. idEntity::ClearSkin
  1297. ================
  1298. */
  1299. void idEntity::ClearSkin( void )  
  1300. {
  1301.     if ( GetAnimator() && GetAnimator()->ModelDef() ) {
  1302.         renderEntity.customSkin = GetAnimator()->ModelDef()->GetDefaultSkin();        
  1303.     } else  {
  1304.         renderEntity.customSkin = NULL;
  1305.     }
  1306.  
  1307.     UpdateVisuals();
  1308. }
  1309. // RAVEN END
  1310.  
  1311. /*
  1312. ================
  1313. idEntity::GetSkin
  1314. ================
  1315. */
  1316. const idDeclSkin *idEntity::GetSkin( void ) const {
  1317.     return renderEntity.customSkin;
  1318. }
  1319.  
  1320. /*
  1321. ================
  1322. idEntity::FreeModelDef
  1323. ================
  1324. */
  1325. void idEntity::FreeModelDef( void ) {
  1326.     if ( modelDefHandle != -1 ) {
  1327.         gameRenderWorld->FreeEntityDef( modelDefHandle );
  1328.         modelDefHandle = -1;
  1329.  
  1330.         rvClientEntity* cent;
  1331.  
  1332.         for( cent = clientEntities.Next(); cent != NULL; cent = cent->bindNode.Next() ) {
  1333.             cent->FreeEntityDef();
  1334.         }    
  1335.     }    
  1336. }
  1337.  
  1338. /*
  1339. ================
  1340. idEntity::FreeLightDef
  1341. ================
  1342. */
  1343. void idEntity::FreeLightDef( void ) {
  1344. }
  1345.  
  1346. /*
  1347. ================
  1348. idEntity::IsHidden
  1349. ================
  1350. */
  1351. bool idEntity::IsHidden( void ) const {
  1352.     return fl.hidden;
  1353. }
  1354.  
  1355. /*
  1356. ================
  1357. idEntity::Hide
  1358. ================
  1359. */
  1360. void idEntity::Hide( void ) {
  1361.     if ( !IsHidden() ) {
  1362.         fl.hidden = true;
  1363.         FreeModelDef();
  1364.         UpdateVisuals();
  1365.     }
  1366. }
  1367.  
  1368. /*
  1369. ================
  1370. idEntity::Show
  1371. ================
  1372. */
  1373. void idEntity::Show( void ) {
  1374.     if ( IsHidden() ) {
  1375.         fl.hidden = false;
  1376.         UpdateVisuals();
  1377.     }
  1378. }
  1379.  
  1380. /*
  1381. ================
  1382. idEntity::UpdateModelTransform
  1383. ================
  1384. */
  1385. void idEntity::UpdateModelTransform( void ) {
  1386.     idVec3 origin;
  1387.     idMat3 axis;
  1388.  
  1389.     if ( GetPhysicsToVisualTransform( origin, axis ) ) {
  1390.         renderEntity.axis = axis * GetPhysics()->GetAxis();
  1391.         renderEntity.origin = GetPhysics()->GetOrigin() + origin * renderEntity.axis;
  1392.     } else {
  1393.         renderEntity.axis = GetPhysics()->GetAxis();
  1394.         renderEntity.origin = GetPhysics()->GetOrigin();
  1395.     }
  1396. }
  1397.  
  1398. /*
  1399. ================
  1400. idEntity::UpdateModel
  1401. ================
  1402. */
  1403. void idEntity::UpdateModel( void ) {
  1404.     UpdateModelTransform();
  1405.  
  1406. // RAVEN BEGIN
  1407. // abahr: moved GetAnimator call because its invalid when called from a destructor
  1408.     UpdateRenderEntityCallback();
  1409. // RAVEN END
  1410.  
  1411.     // set to invalid number to force an update the next time the PVS areas are retrieved
  1412.     ClearPVSAreas();
  1413.  
  1414.     // ensure that we call Present this frame
  1415.     BecomeActive( TH_UPDATEVISUALS );
  1416. }
  1417.  
  1418. // RAVEN BEGIN
  1419. // abahr:
  1420. /*
  1421. ================
  1422. idEntity::UpdateRenderEntityCallback
  1423. ================
  1424. */
  1425. void idEntity::UpdateRenderEntityCallback() {
  1426. }
  1427. // RAVEN END
  1428.  
  1429. /*
  1430. ================
  1431. idEntity::UpdateVisuals
  1432. ================
  1433. */
  1434. void idEntity::UpdateVisuals( void ) {
  1435.     UpdateModel();
  1436.     UpdateSound();
  1437. }
  1438.  
  1439. /*
  1440. ================
  1441. idEntity::UpdatePVSAreas
  1442. ================
  1443. */
  1444. void idEntity::UpdatePVSAreas( void ) {
  1445.     int localNumPVSAreas, localPVSAreas[32];
  1446.     idBounds modelAbsBounds;
  1447.     int i;
  1448.  
  1449.     modelAbsBounds.FromTransformedBounds( renderEntity.bounds, renderEntity.origin, renderEntity.axis );
  1450.     localNumPVSAreas = gameLocal.pvs.GetPVSAreas( modelAbsBounds, localPVSAreas, sizeof( localPVSAreas ) / sizeof( localPVSAreas[0] ) );
  1451.  
  1452.     // FIXME: some particle systems may have huge bounds and end up in many PVS areas
  1453.     // the first MAX_PVS_AREAS may not be visible to a network client and as a result the particle system may not show up when it should
  1454.     if ( localNumPVSAreas > MAX_PVS_AREAS ) {
  1455.         localNumPVSAreas = gameLocal.pvs.GetPVSAreas( idBounds( renderEntity.origin ).Expand( 64.0f ), localPVSAreas, sizeof( localPVSAreas ) / sizeof( localPVSAreas[0] ) );
  1456.     }
  1457.  
  1458.     for ( numPVSAreas = 0; numPVSAreas < MAX_PVS_AREAS && numPVSAreas < localNumPVSAreas; numPVSAreas++ ) {
  1459.         PVSAreas[numPVSAreas] = localPVSAreas[numPVSAreas];
  1460.     }
  1461.  
  1462.     for( i = numPVSAreas; i < MAX_PVS_AREAS; i++ ) {
  1463.         PVSAreas[ i ] = 0;
  1464.     }
  1465. }
  1466.  
  1467. /*
  1468. ================
  1469. idEntity::UpdatePVSAreas
  1470. ================
  1471. */
  1472. void idEntity::UpdatePVSAreas( const idVec3 &pos ) {
  1473.     int i;
  1474.  
  1475.     numPVSAreas = gameLocal.pvs.GetPVSAreas( idBounds( pos ), PVSAreas, MAX_PVS_AREAS );
  1476.     i = numPVSAreas;
  1477.     while ( i < MAX_PVS_AREAS ) {
  1478.         PVSAreas[ i++ ] = 0;
  1479.     }
  1480. }
  1481.  
  1482. /*
  1483. ================
  1484. idEntity::GetNumPVSAreas
  1485. ================
  1486. */
  1487. int idEntity::GetNumPVSAreas( void ) {
  1488.     if ( numPVSAreas < 0 ) {
  1489.         UpdatePVSAreas();
  1490.     }
  1491.     return numPVSAreas;
  1492. }
  1493.  
  1494. /*
  1495. ================
  1496. idEntity::GetPVSAreas
  1497. ================
  1498. */
  1499. const int *idEntity::GetPVSAreas( void ) {
  1500.     if ( numPVSAreas < 0 ) {
  1501.         UpdatePVSAreas();
  1502.     }
  1503.     return PVSAreas;
  1504. }
  1505.  
  1506. /*
  1507. ================
  1508. idEntity::ClearPVSAreas
  1509. ================
  1510. */
  1511. void idEntity::ClearPVSAreas( void ) {
  1512.     numPVSAreas = -1;
  1513. }
  1514.  
  1515. /*
  1516. ================
  1517. idEntity::PhysicsTeamInPVS
  1518.  
  1519.   FIXME: for networking also return true if any of the entity shadows is in the PVS
  1520. ================
  1521. */
  1522. bool idEntity::PhysicsTeamInPVS( pvsHandle_t pvsHandle ) {
  1523.     idEntity *part;
  1524.  
  1525.     if ( teamMaster ) {
  1526.         for ( part = teamMaster; part; part = part->teamChain ) {
  1527.             if ( gameLocal.pvs.InCurrentPVS( pvsHandle, part->GetPVSAreas(), part->GetNumPVSAreas() ) ) {
  1528.                 return true;
  1529.             }
  1530.         }
  1531.     } else {
  1532.         return gameLocal.pvs.InCurrentPVS( pvsHandle, GetPVSAreas(), GetNumPVSAreas() );
  1533.     }
  1534.     return false;
  1535. }
  1536.  
  1537. /*
  1538. ==============
  1539. idEntity::ProjectOverlay
  1540. ==============
  1541. */
  1542. void idEntity::ProjectOverlay( const idVec3 &origin, const idVec3 &dir, float size, const char *material ) {
  1543.     float s, c;
  1544.     idMat3 axis, axistemp;
  1545.     idVec3 localOrigin, localAxis[2];
  1546.     idPlane localPlane[2];
  1547.  
  1548.     // make sure the entity has a valid model handle
  1549.     if ( modelDefHandle < 0 ) {
  1550.         return;
  1551.     }
  1552.  
  1553.     // only do this on dynamic md5 models
  1554.     if ( renderEntity.hModel->IsDynamicModel() != DM_CACHED ) {
  1555.         return;
  1556.     }
  1557.  
  1558.     idMath::SinCos16( gameLocal.random.RandomFloat() * idMath::TWO_PI, s, c );
  1559.  
  1560.     axis[2] = -dir;
  1561.     axis[2].NormalVectors( axistemp[0], axistemp[1] );
  1562.     axis[0] = axistemp[ 0 ] * c + axistemp[ 1 ] * -s;
  1563.     axis[1] = axistemp[ 0 ] * -s + axistemp[ 1 ] * -c;
  1564.  
  1565.     renderEntity.axis.ProjectVector( origin - renderEntity.origin, localOrigin );
  1566.     renderEntity.axis.ProjectVector( axis[0], localAxis[0] );
  1567.     renderEntity.axis.ProjectVector( axis[1], localAxis[1] );
  1568.  
  1569.     size = 1.0f / size;
  1570.     localAxis[0] *= size;
  1571.     localAxis[1] *= size;
  1572.  
  1573.     localPlane[0] = localAxis[0];
  1574.     localPlane[0][3] = -( localOrigin * localAxis[0] ) + 0.5f;
  1575.  
  1576.     localPlane[1] = localAxis[1];
  1577.     localPlane[1][3] = -( localOrigin * localAxis[1] ) + 0.5f;
  1578.  
  1579.     const idMaterial *mtr = declManager->FindMaterial( material );
  1580.  
  1581.     // project an overlay onto the model
  1582.     gameRenderWorld->ProjectOverlay( modelDefHandle, localPlane, mtr );
  1583.  
  1584.     // make sure non-animating models update their overlay
  1585.     UpdateVisuals();
  1586. }
  1587.  
  1588. /*
  1589. ================
  1590. idEntity::Present
  1591.  
  1592. Present is called to allow entities to generate refEntities, lights, etc for the renderer.
  1593. ================
  1594. */
  1595. void idEntity::Present( void ) {
  1596.  
  1597.     if ( !gameLocal.isNewFrame ) {
  1598.         return;
  1599.     }
  1600.  
  1601.     // if there is no handle yet, go ahead and add it, ignoring the last predict frame early out
  1602.     // if not, that causes next render frame to have a bunch of spurious primitive draws ( r_showPrimitives )
  1603.     // ( we suspect this is because TH_UPDATEVISUALS doesn't get cleared? )
  1604.     if ( !gameLocal.isLastPredictFrame && modelDefHandle != -1 ) {
  1605.         return;
  1606.     }
  1607.  
  1608. // RAVEN BEGIN
  1609. // ddynerman: don't render objects not in our instance (only on server)
  1610.     if ( gameLocal.isServer && gameLocal.GetLocalPlayer() && gameLocal.GetLocalPlayer()->GetInstance() != GetInstance() ) {
  1611.         FreeModelDef();
  1612.         return;
  1613.     }
  1614. // RAVEN END
  1615.  
  1616.     // don't present to the renderer if the entity hasn't changed
  1617.     if ( !( thinkFlags & TH_UPDATEVISUALS ) ) {
  1618.         return;
  1619.     }
  1620.     BecomeInactive( TH_UPDATEVISUALS );
  1621.  
  1622.     // camera target for remote render views
  1623. // RAVEN BEGIN
  1624. // rjohnson: removed PVS check for when func_static's are not starting in your PVS
  1625.     if ( cameraTarget ) { // && gameLocal.InPlayerPVS( this ) ) {
  1626. // RAVEN END
  1627.         renderEntity.remoteRenderView = cameraTarget->GetRenderView();
  1628.     }
  1629.  
  1630.     // if set to invisible, skip
  1631.     if ( !renderEntity.hModel || IsHidden() ) {
  1632.         return;
  1633.     }
  1634.  
  1635.     // add to refresh list
  1636.     if ( modelDefHandle == -1 ) {
  1637.         modelDefHandle = gameRenderWorld->AddEntityDef( &renderEntity );
  1638.     } else {
  1639.         gameRenderWorld->UpdateEntityDef( modelDefHandle, &renderEntity );
  1640.     }    
  1641. }
  1642.  
  1643. /*
  1644. ================
  1645. idEntity::UpdateRenderEntity
  1646. ================
  1647. */
  1648. bool idEntity::UpdateRenderEntity( renderEntity_s *renderEntity, const renderView_t *renderView ) {
  1649.     if ( gameLocal.inCinematic && gameLocal.skipCinematic ) {
  1650.         return false;
  1651.     }
  1652.  
  1653.     idAnimator *animator = GetAnimator();
  1654.     if ( animator ) {
  1655.         return animator->CreateFrame( gameLocal.time, false );
  1656.     }
  1657.  
  1658.     return false;
  1659. }
  1660.  
  1661. /*
  1662. ================
  1663. idEntity::ModelCallback
  1664.  
  1665.     NOTE: may not change the game state whatsoever!
  1666. ================
  1667. */
  1668. bool idEntity::ModelCallback( renderEntity_s *renderEntity, const renderView_t *renderView ) {
  1669.     idEntity *ent;
  1670.  
  1671.     ent = gameLocal.entities[ renderEntity->entityNum ];
  1672.     if ( !ent ) {
  1673.         gameLocal.Error( "idEntity::ModelCallback: callback with NULL game entity '%d'", renderEntity->entityNum );
  1674.     }
  1675.  
  1676.     return ent->UpdateRenderEntity( renderEntity, renderView );
  1677. }
  1678.  
  1679. /*
  1680. ================
  1681. idEntity::GetAnimator
  1682.  
  1683. Subclasses will be responsible for allocating animator.
  1684. ================
  1685. */
  1686. idAnimator *idEntity::GetAnimator( void ) {
  1687.     return NULL;
  1688. }
  1689.  
  1690. /*
  1691. =============
  1692. idEntity::GetRenderView
  1693.  
  1694. This is used by remote camera views to look from an entity
  1695. =============
  1696. */
  1697. renderView_t *idEntity::GetRenderView( void ) {
  1698.     if ( !renderView ) {
  1699.         renderView = new renderView_t;
  1700.     }
  1701.     memset( renderView, 0, sizeof( *renderView ) );
  1702.  
  1703.     renderView->vieworg = GetPhysics()->GetOrigin();
  1704.     renderView->fov_x = 120;
  1705.     renderView->fov_y = 120;
  1706.     renderView->viewaxis = GetPhysics()->GetAxis();
  1707.  
  1708.     // copy global shader parms
  1709.     for( int i = 0; i < MAX_GLOBAL_SHADER_PARMS; i++ ) {
  1710.         renderView->shaderParms[ i ] = gameLocal.globalShaderParms[ i ];
  1711.     }
  1712.  
  1713.     renderView->globalMaterial = gameLocal.GetGlobalMaterial();
  1714.  
  1715.     renderView->time = gameLocal.time;
  1716.  
  1717. // RAVEN BEGIN
  1718. // mwhitlock: Xenon texture streaming.
  1719. #if defined(_XENON)
  1720.     renderView->streamingPrecache = false;
  1721. #endif
  1722. // RAVEN END
  1723.  
  1724.     return renderView;
  1725. }
  1726.  
  1727. // RAVEN BEGIN
  1728. // bdube: added convienince functions for effects
  1729.  
  1730. /***********************************************************************
  1731.  
  1732.   effects
  1733.     
  1734. ***********************************************************************/
  1735.  
  1736. /*
  1737. ================
  1738. idEntity::PlayEffect
  1739. ================
  1740. */
  1741. rvClientEffect* idEntity::PlayEffect( const idDecl *effect, jointHandle_t joint, const idVec3& originOffset, const idMat3& axisOffset, bool loop, const idVec3& endOrigin, bool broadcast, effectCategory_t category, const idVec4& effectTint ) {
  1742.     if ( joint == INVALID_JOINT ) {
  1743.         return NULL;
  1744.     }
  1745.     
  1746.     if ( !effect || !gameLocal.isNewFrame ) {
  1747.         return NULL;
  1748.     }
  1749.  
  1750.     if ( !gameLocal.isClient && broadcast ) {
  1751.         idBitMsg    msg;
  1752.         byte        msgBuf[MAX_EVENT_PARAM_SIZE];
  1753.  
  1754.         msg.Init( msgBuf, sizeof( msgBuf ) );
  1755.         msg.BeginWriting();
  1756.         idGameLocal::WriteDecl( msg, effect );
  1757.         msg.WriteLong( joint );
  1758.         msg.WriteBits( loop, 1 );
  1759.         msg.WriteFloat( endOrigin.x );
  1760.         msg.WriteFloat( endOrigin.y );
  1761.         msg.WriteFloat( endOrigin.z );    
  1762.         msg.WriteByte( category );
  1763.         ServerSendInstanceEvent( EVENT_PLAYEFFECT_JOINT, &msg, false, -1 );
  1764.     }
  1765.  
  1766. // RAVEN BEGIN
  1767. // rjohnson: no effects on dedicated server
  1768.     if ( gameLocal.isMultiplayer && !gameLocal.isClient && !gameLocal.isListenServer ) {
  1769.         // no effects on dedicated server
  1770.         return NULL;
  1771.     }
  1772.  
  1773.     if( bse->Filtered( effect->GetName(), category ) ) {
  1774.         // Effect filtered out
  1775.         return NULL;
  1776.     }
  1777.  
  1778.     if ( gameLocal.isListenServer && gameLocal.GetLocalPlayer() ) {
  1779.         if ( GetInstance() != gameLocal.GetLocalPlayer()->GetInstance() ) {
  1780.             return NULL;
  1781.         }
  1782.     }
  1783. // RAVEN END
  1784.  
  1785.     RV_PUSH_SYS_HEAP_ID(RV_HEAP_ID_MULTIPLE_FRAME);
  1786.     rvClientEffect* clientEffect = new rvClientEffect( effect );
  1787.     RV_POP_HEAP();
  1788.  
  1789.     clientEffect->SetOrigin ( originOffset );
  1790.     clientEffect->SetAxis ( axisOffset );
  1791.     clientEffect->Bind ( this, joint );
  1792.     clientEffect->SetGravity( gameLocal.GetCurrentGravity( this ) );
  1793.  
  1794.     if ( !clientEffect->Play ( gameLocal.time, loop, endOrigin ) ) {
  1795.         delete clientEffect;
  1796.         return NULL;
  1797.     }
  1798.     
  1799.     clientEffect->GetRenderEffect()->shaderParms[ SHADERPARM_RED ]        = effectTint[ 0 ];
  1800.     clientEffect->GetRenderEffect()->shaderParms[ SHADERPARM_GREEN ]    = effectTint[ 1 ];
  1801.     clientEffect->GetRenderEffect()->shaderParms[ SHADERPARM_BLUE ]        = effectTint[ 2 ];
  1802.     clientEffect->GetRenderEffect()->shaderParms[ SHADERPARM_ALPHA ]    = effectTint[ 3 ];
  1803.  
  1804.     return clientEffect;
  1805. }
  1806.  
  1807. rvClientEffect* idEntity::PlayEffect( const idDecl *effect, const idVec3& origin, const idMat3& axis, bool loop, const idVec3& endOrigin, bool broadcast, effectCategory_t category, const idVec4& effectTint ) {
  1808.     idVec3 localOrigin;
  1809.     idMat3 localAxis;
  1810.     
  1811.     if ( !effect || !gameLocal.isNewFrame ) {
  1812.         return NULL;
  1813.     }
  1814.  
  1815.     if ( entityNumber == ENTITYNUM_WORLD ) {
  1816.         return gameLocal.PlayEffect( effect, origin, axis, loop, endOrigin, broadcast, category, effectTint );
  1817.     }
  1818.  
  1819.     // Calculate the local origin and axis from the given globals
  1820.     localOrigin = (origin - renderEntity.origin) * renderEntity.axis.Transpose ( );
  1821.     localAxis   = axis * renderEntity.axis.Transpose();
  1822.  
  1823.     if ( !gameLocal.isClient && broadcast ) {
  1824.         idBitMsg    msg;
  1825.         byte        msgBuf[MAX_EVENT_PARAM_SIZE];
  1826.         idCQuat        quat;
  1827.         
  1828.         quat = localAxis.ToCQuat();
  1829.  
  1830.         msg.Init( msgBuf, sizeof( msgBuf ) );
  1831.         msg.BeginWriting();
  1832.         idGameLocal::WriteDecl( msg, effect );
  1833.         msg.WriteFloat( localOrigin.x );
  1834.         msg.WriteFloat( localOrigin.y );
  1835.         msg.WriteFloat( localOrigin.z );
  1836.         msg.WriteFloat( quat.x );
  1837.         msg.WriteFloat( quat.y );
  1838.         msg.WriteFloat( quat.z );
  1839.         msg.WriteBits( loop, 1 );
  1840.         msg.WriteFloat( endOrigin.x );
  1841.         msg.WriteFloat( endOrigin.y );
  1842.         msg.WriteFloat( endOrigin.z );    
  1843.         msg.WriteByte( category );
  1844.         ServerSendInstanceEvent( EVENT_PLAYEFFECT, &msg, false, -1 );
  1845.     }
  1846.  
  1847. // RAVEN BEGIN
  1848. // rjohnson: no effects on dedicated server
  1849.     if ( gameLocal.isMultiplayer && !gameLocal.isClient && !gameLocal.isListenServer ) {
  1850.         // no effects on dedicated server
  1851.         return NULL;
  1852.     }
  1853.  
  1854.     if( bse->Filtered( effect->GetName(), category ) ) {
  1855.         // Effect filtered out
  1856.         return( NULL );
  1857.     }
  1858. // ddynerman: a listen server might get this far re: playing effects, don't actually play out of instance effects
  1859.     if ( gameLocal.isListenServer && gameLocal.GetLocalPlayer() ) {
  1860.         if ( GetInstance() != gameLocal.GetLocalPlayer()->GetInstance() ) {
  1861.             return NULL;
  1862.         }
  1863.     }
  1864. // RAVEN END
  1865.  
  1866. // RAVEN BEGIN
  1867. // mwhitlock: Dynamic memory consolidation
  1868.     RV_PUSH_SYS_HEAP_ID(RV_HEAP_ID_MULTIPLE_FRAME);
  1869. // RAVEN END
  1870.     rvClientEffect* clientEffect = new rvClientEffect ( effect );
  1871. // RAVEN BEGIN
  1872. // mwhitlock: Dynamic memory consolidation
  1873.     RV_POP_HEAP();
  1874. // RAVEN END
  1875.     clientEffect->SetOrigin ( localOrigin );
  1876.     clientEffect->SetAxis ( localAxis );
  1877.     clientEffect->Bind ( this );
  1878.     clientEffect->SetGravity( gameLocal.GetCurrentGravity( this ) );
  1879.  
  1880.     if ( !clientEffect->Play ( gameLocal.time, loop, endOrigin ) ) {
  1881.         delete clientEffect;
  1882.         return NULL;
  1883.     }
  1884.     
  1885.     clientEffect->GetRenderEffect()->shaderParms[ SHADERPARM_RED ]        = effectTint[ 0 ];
  1886.     clientEffect->GetRenderEffect()->shaderParms[ SHADERPARM_GREEN ]    = effectTint[ 1 ];
  1887.     clientEffect->GetRenderEffect()->shaderParms[ SHADERPARM_BLUE ]        = effectTint[ 2 ];
  1888.     clientEffect->GetRenderEffect()->shaderParms[ SHADERPARM_ALPHA ]    = effectTint[ 3 ];
  1889.  
  1890.     return clientEffect;
  1891. }
  1892.  
  1893. /*
  1894. ================
  1895. idEntity::StopAllEffects
  1896. ================
  1897. */
  1898. void idEntity::StopAllEffects( bool destroyParticles ) {
  1899.     rvClientEntity* cent;
  1900.     rvClientEntity* next;
  1901.  
  1902.     for( cent = clientEntities.Next(); cent != NULL; cent = next ) {
  1903.         next = cent->bindNode.Next();
  1904. // RAVEN BEGIN
  1905. // jnewquist: Use accessor for static class type 
  1906.         if ( cent->IsType ( rvClientEffect::GetClassType() ) ) {
  1907. // RAVEN END
  1908.             static_cast<rvClientEffect *>( cent )->Stop( destroyParticles );
  1909.         }
  1910.     }        
  1911. }
  1912.  
  1913. /*
  1914. ================
  1915. idEntity::StopEffect
  1916. ================
  1917. */
  1918. void idEntity::StopEffect( const idDecl *effect, bool destroyParticles ) {    
  1919.     rvClientEntity*    cent;
  1920.     rvClientEntity*    next;
  1921.     
  1922.     if( !effect ) {
  1923.         return;
  1924.     }
  1925.  
  1926.     // Build a list of all the effects to stop    
  1927.     for( cent = clientEntities.Next(); cent != NULL; cent = next ) {
  1928.         next = cent->bindNode.Next();
  1929.         
  1930.         // Is this client entity an effect?
  1931. // RAVEN BEGIN
  1932. // jnewquist: Use accessor for static class type 
  1933.         if ( !cent->IsType( rvClientEffect::GetClassType() ) ) {
  1934. // RAVEN END
  1935.             continue;
  1936.         }
  1937.         
  1938.         // Now check to make sure its the specific effect we want to stop        
  1939.         rvClientEffect* clientEffect;
  1940.         clientEffect = static_cast<rvClientEffect *>( cent );
  1941.         if ( clientEffect->GetEffectIndex ( ) == effect->Index() ) {
  1942.             clientEffect->Stop ( destroyParticles );
  1943.         }
  1944.     }
  1945. }
  1946.  
  1947. void idEntity::StopEffect ( const char* effectName, bool destroyParticles ) {
  1948.     StopEffect ( gameLocal.GetEffect ( spawnArgs, effectName ), destroyParticles );
  1949. }
  1950.  
  1951. // RAVEN END
  1952.  
  1953. /***********************************************************************
  1954.  
  1955.   Sound
  1956.     
  1957. ***********************************************************************/
  1958.  
  1959. /*
  1960. ================
  1961. idEntity::CanPlayChatterSounds
  1962.  
  1963. Used for playing chatter sounds on monsters.
  1964. ================
  1965. */
  1966. bool idEntity::CanPlayChatterSounds( void ) const {
  1967.     return true;
  1968. }
  1969.  
  1970. /*
  1971. ================
  1972. idEntity::StartSound
  1973. ================
  1974. */
  1975. bool idEntity::StartSound( const char *soundName, const s_channelType channel, int soundShaderFlags, bool broadcast, int *length ) {
  1976.     const idSoundShader *shader;
  1977.     const char *sound;
  1978.  
  1979.     if ( length ) {
  1980.         *length = 0;
  1981.     }
  1982.  
  1983.     // we should ALWAYS be playing sounds from the def.
  1984.     // hardcoded sounds MUST be avoided at all times because they won't get precached.
  1985.     idStr soundNameStr = soundName;
  1986.     if( soundNameStr.CmpPrefix( "snd_" ) && soundNameStr.CmpPrefix( "lipsync_" ) ) {
  1987.         common->Warning( "Non precached sound \'%s\'", soundName );
  1988.     }
  1989.  
  1990.     if ( !spawnArgs.GetString( soundName, "", &sound ) ) {
  1991.         return false;
  1992.     }
  1993.  
  1994.     if ( *sound == '\0' ) {
  1995.         return false;
  1996.     }
  1997.  
  1998.     if ( !gameLocal.isNewFrame ) {
  1999.         // don't play the sound, but don't report an error
  2000.         return true;
  2001.     }
  2002.  
  2003.     shader = declManager->FindSound( sound );
  2004.     return StartSoundShader( shader, channel, soundShaderFlags, broadcast, length );
  2005. }
  2006.  
  2007. /*
  2008. ================
  2009. idEntity::StartSoundShader
  2010. ================
  2011. */
  2012. bool idEntity::StartSoundShader( const idSoundShader *shader, const s_channelType channel, int soundShaderFlags, bool broadcast, int *length ) {
  2013.     float diversity;
  2014.     int len;
  2015.  
  2016.     if ( length ) {
  2017.         *length = 0;
  2018.     }
  2019.  
  2020.     if ( !shader ) {
  2021.         return false;
  2022.     }
  2023.  
  2024.     if ( !gameLocal.isNewFrame ) {
  2025.         return true;
  2026.     }
  2027.  
  2028.     if ( gameLocal.isServer && broadcast ) {
  2029.         idBitMsg    msg;
  2030.         byte        msgBuf[MAX_EVENT_PARAM_SIZE];
  2031.  
  2032.         msg.Init( msgBuf, sizeof( msgBuf ) );
  2033.         msg.BeginWriting();
  2034.         idGameLocal::WriteDecl( msg, shader );
  2035.         msg.WriteByte( channel );
  2036.         ServerSendInstanceEvent( EVENT_STARTSOUNDSHADER, &msg, false, -1 );
  2037.     }
  2038.  
  2039.     // in MP, don't play sounds from other instances
  2040.     if( gameLocal.isMultiplayer && gameLocal.GetLocalPlayer() && gameLocal.GetLocalPlayer()->GetInstance() != instance ) {
  2041.         return false;
  2042.     }
  2043.  
  2044. // rjohnson: don't play sounds on a dedicated server!
  2045.     if ( gameLocal.isMultiplayer && !gameLocal.isClient && !gameLocal.isListenServer ) {
  2046.         return false;
  2047.     }
  2048.  
  2049.     // set a random value for diversity unless one was parsed from the entity
  2050.     if ( refSound.diversity < 0.0f ) {
  2051.         diversity = gameLocal.random.RandomFloat();
  2052.     } else {
  2053.         diversity = refSound.diversity;
  2054.     }
  2055.  
  2056. // RAVEN BEGIN
  2057.     // if we don't have a soundEmitter allocated yet, get one now
  2058.     if ( !soundSystem->EmitterForIndex( SOUNDWORLD_GAME, refSound.referenceSoundHandle ) ) {
  2059.         refSound.referenceSoundHandle = soundSystem->AllocSoundEmitter( SOUNDWORLD_GAME );
  2060.     }
  2061.  
  2062.     UpdateSound();
  2063.  
  2064.     idSoundEmitter *emitter = soundSystem->EmitterForIndex( SOUNDWORLD_GAME, refSound.referenceSoundHandle );
  2065.     if ( emitter ) {
  2066.         emitter->UpdateEmitter( refSound.origin, refSound.velocity, refSound.listenerId, &refSound.parms );
  2067.         len = emitter->StartSound( shader, channel, diversity, soundShaderFlags );
  2068.         if ( length ) {
  2069.             *length = len;
  2070.         }
  2071.     }
  2072. // RAVEN END
  2073.  
  2074.     // set reference to the sound for shader synced effects
  2075.     renderEntity.referenceSoundHandle = refSound.referenceSoundHandle;
  2076.  
  2077.     return true;
  2078. }
  2079.  
  2080. /*
  2081. ================
  2082. idEntity::StopSound
  2083. ================
  2084. */
  2085. void idEntity::StopSound( const s_channelType channel, bool broadcast ) {
  2086.     if ( !gameLocal.isNewFrame ) {
  2087.         return;
  2088.     }
  2089.  
  2090.     if ( gameLocal.isServer && broadcast ) {
  2091.         idBitMsg    msg;
  2092.         byte        msgBuf[MAX_EVENT_PARAM_SIZE];
  2093.  
  2094.         msg.Init( msgBuf, sizeof( msgBuf ) );
  2095.         msg.BeginWriting();
  2096.         msg.WriteByte( channel );
  2097.         ServerSendInstanceEvent( EVENT_STOPSOUNDSHADER, &msg, false, -1 );
  2098.     }
  2099.  
  2100.     // in MP, don't play sounds from other instances
  2101.     if( gameLocal.isMultiplayer && gameLocal.GetLocalPlayer() && gameLocal.GetLocalPlayer()->GetInstance() != instance ) {
  2102.         return;
  2103.     }
  2104.  
  2105. // RAVEN BEGIN
  2106.     idSoundEmitter *emitter = soundSystem->EmitterForIndex( SOUNDWORLD_GAME, refSound.referenceSoundHandle );
  2107.     if ( emitter ) {
  2108.         emitter->StopSound( channel );
  2109.     }
  2110. // RAVEN END
  2111. }
  2112.  
  2113. /*
  2114. ================
  2115. idEntity::SetSoundVolume
  2116.  
  2117.   Must be called before starting a new sound.
  2118. ================
  2119. */
  2120. void idEntity::SetSoundVolume( float volume ) {
  2121.     refSound.parms.volume = volume;
  2122. }
  2123.  
  2124. /*
  2125. ================
  2126. idEntity::UpdateSound
  2127. ================
  2128. */
  2129. void idEntity::UpdateSound( void ) {
  2130. // RAVEN BEGIN
  2131.     idSoundEmitter *emitter = soundSystem->EmitterForIndex( SOUNDWORLD_GAME, refSound.referenceSoundHandle );
  2132.     if ( emitter ) {
  2133. // RAVEN END
  2134.         idVec3 origin;
  2135.         idMat3 axis;
  2136.  
  2137.         if ( GetPhysicsToSoundTransform( origin, axis ) ) {
  2138.             refSound.origin = GetPhysics()->GetOrigin() + origin * axis;
  2139.         } else {
  2140.             refSound.origin = GetPhysics()->GetOrigin();
  2141.         }
  2142.  
  2143. // RAVEN BEGIN
  2144.         refSound.velocity = GetPhysics()->GetLinearVelocity();
  2145.         emitter->UpdateEmitter( refSound.origin, refSound.velocity, refSound.listenerId, &refSound.parms );
  2146. // RAVEN END
  2147.     }
  2148. }
  2149.  
  2150. /*
  2151. ================
  2152. idEntity::GetListenerId
  2153. ================
  2154. */
  2155. int idEntity::GetListenerId( void ) const {
  2156.     return refSound.listenerId;
  2157. }
  2158.  
  2159. /*
  2160. ================
  2161. idEntity::GetSoundEmitter
  2162. ================
  2163. */
  2164. // RAVEN BEGIN
  2165. int idEntity::GetSoundEmitter( void ) const {
  2166.     return( refSound.referenceSoundHandle );
  2167. // RAVEN END
  2168. }
  2169.  
  2170. /*
  2171. ================
  2172. idEntity::FreeSoundEmitter
  2173. ================
  2174. */
  2175. void idEntity::FreeSoundEmitter( bool immediate ) {
  2176. // RAVEN BEGIN
  2177.     soundSystem->FreeSoundEmitter( SOUNDWORLD_GAME, refSound.referenceSoundHandle, immediate );
  2178.     refSound.referenceSoundHandle = -1;
  2179. // RAVEN END
  2180. }
  2181.  
  2182. // RAVEN BEGIN
  2183. // bdube: client entities
  2184.  
  2185. /***********************************************************************
  2186.  
  2187.   client entities
  2188.     
  2189. ***********************************************************************/
  2190.  
  2191. /*
  2192. ================
  2193. idEntity::RemoveClientEntities
  2194. ================
  2195. */
  2196. void idEntity::RemoveClientEntities( void ) {
  2197.     rvClientEntity* cent;
  2198.     // Unbinding should remove the node from the list so keep using the head until
  2199.     // there are no more entities
  2200.     for( cent = clientEntities.Next(); cent != NULL; cent = clientEntities.Next() ) {
  2201.         cent->Unbind( );
  2202.         delete cent;
  2203.     }        
  2204.     clientEntities.Clear( );
  2205. }
  2206. // RAVEN END
  2207.  
  2208. /***********************************************************************
  2209.  
  2210.   entity binding
  2211.     
  2212. ***********************************************************************/
  2213.  
  2214. /*
  2215. ================
  2216. idEntity::PreBind
  2217. ================
  2218. */
  2219. void idEntity::PreBind( void ) {
  2220. }
  2221.  
  2222. /*
  2223. ================
  2224. idEntity::PostBind
  2225. ================
  2226. */
  2227. void idEntity::PostBind( void ) {
  2228. }
  2229.  
  2230. /*
  2231. ================
  2232. idEntity::PreUnbind
  2233. ================
  2234. */
  2235. void idEntity::PreUnbind( void ) {
  2236. }
  2237.  
  2238. /*
  2239. ================
  2240. idEntity::PostUnbind
  2241. ================
  2242. */
  2243. void idEntity::PostUnbind( void ) {
  2244. }
  2245.  
  2246. /*
  2247. ================
  2248. idEntity::InitBind
  2249. ================
  2250. */
  2251. bool idEntity::InitBind( idEntity *master ) {
  2252.  
  2253.     if ( master == this ) {
  2254.         gameLocal.Error( "Tried to bind an object to itself." );
  2255.         return false;
  2256.     }
  2257.  
  2258.     if ( this == gameLocal.world ) {
  2259.         gameLocal.Error( "Tried to bind world to another entity" );
  2260.         return false;
  2261.     }
  2262.  
  2263.     // unbind myself from my master
  2264.     Unbind();
  2265.  
  2266.     // add any bind constraints to an articulated figure
  2267. // RAVEN BEGIN
  2268. // jnewquist: Use accessor for static class type 
  2269.     if ( master && IsType( idAFEntity_Base::GetClassType() ) ) {
  2270. // RAVEN END
  2271.         static_cast<idAFEntity_Base *>(this)->AddBindConstraints();
  2272.     }
  2273.  
  2274.     if ( !master || master == gameLocal.world ) {
  2275.         // this can happen in scripts, so safely exit out.
  2276.         return false;
  2277.     }
  2278.  
  2279.     return true;
  2280. }
  2281.  
  2282. /*
  2283. ================
  2284. idEntity::FinishBind
  2285. ================
  2286. */
  2287. void idEntity::FinishBind( void ) {
  2288.  
  2289.     // set the master on the physics object
  2290.     physics->SetMaster( bindMaster, fl.bindOrientated );
  2291.  
  2292.     // We are now separated from our previous team and are either
  2293.     // an individual, or have a team of our own.  Now we can join
  2294.     // the new bindMaster's team.  Bindmaster must be set before
  2295.     // joining the team, or we will be placed in the wrong position
  2296.     // on the team.
  2297.     JoinTeam( bindMaster );
  2298.  
  2299.     // if our bindMaster is enabled during a cinematic, we must be, too
  2300. // RAVEN BEGIN
  2301. // rjohnson: players should always have cinematic turned on, no matter what
  2302.     if ( !IsType ( idPlayer::GetClassType() ) ) {
  2303.         cinematic = bindMaster->cinematic;
  2304.     }
  2305. // RAVEN END
  2306.  
  2307.     // make sure the team master is active so that physics get run
  2308.     teamMaster->BecomeActive( TH_PHYSICS );
  2309. }
  2310.  
  2311. /*
  2312. ================
  2313. idEntity::Bind
  2314.  
  2315.   bind relative to the visual position of the master
  2316. ================
  2317. */
  2318. void idEntity::Bind( idEntity *master, bool orientated ) {
  2319.  
  2320.     if ( !InitBind( master ) ) {
  2321.         return;
  2322.     }
  2323.  
  2324.     PreBind();
  2325.  
  2326.     bindJoint = INVALID_JOINT;
  2327.     bindBody = -1;
  2328.     bindMaster = master;
  2329.     fl.bindOrientated = orientated;
  2330.  
  2331.     FinishBind();
  2332.  
  2333.     PostBind( );
  2334. }
  2335.  
  2336. /*
  2337. ================
  2338. idEntity::BindToJoint
  2339.  
  2340.   bind relative to a joint of the md5 model used by the master
  2341. ================
  2342. */
  2343. void idEntity::BindToJoint( idEntity *master, const char *jointname, bool orientated ) {
  2344.     jointHandle_t    jointnum;
  2345.     idAnimator        *masterAnimator;
  2346.  
  2347.     if ( !InitBind( master ) ) {
  2348.         return;
  2349.     }
  2350.  
  2351.     masterAnimator = master->GetAnimator();
  2352.     if ( !masterAnimator ) {
  2353.         gameLocal.Warning( "idEntity::BindToJoint: entity '%s' cannot support skeletal models.", master->GetName() );
  2354.         return;
  2355.     }
  2356.  
  2357.     jointnum = masterAnimator->GetJointHandle( jointname );
  2358.     if ( jointnum == INVALID_JOINT ) {
  2359.         gameLocal.Warning( "idEntity::BindToJoint: joint '%s' not found on entity '%s'.", jointname, master->GetName() );
  2360.     }
  2361.  
  2362.     PreBind();
  2363.  
  2364.     bindJoint = jointnum;
  2365.     bindBody = -1;
  2366.     bindMaster = master;
  2367.     fl.bindOrientated = orientated;
  2368.  
  2369.     FinishBind();
  2370.  
  2371.     PostBind();
  2372. }
  2373.  
  2374. /*
  2375. ================
  2376. idEntity::BindToJoint
  2377.  
  2378.   bind relative to a joint of the md5 model used by the master
  2379. ================
  2380. */
  2381. void idEntity::BindToJoint( idEntity *master, jointHandle_t jointnum, bool orientated ) {
  2382.  
  2383.     if ( !InitBind( master ) ) {
  2384.         return;
  2385.     }
  2386.  
  2387.     PreBind();
  2388.  
  2389.     bindJoint = jointnum;
  2390.     bindBody = -1;
  2391.     bindMaster = master;
  2392.     fl.bindOrientated = orientated;
  2393.  
  2394.     FinishBind();
  2395.  
  2396.     PostBind();
  2397. }
  2398.  
  2399. /*
  2400. ================
  2401. idEntity::BindToBody
  2402.  
  2403.   bind relative to a collision model used by the physics of the master
  2404. ================
  2405. */
  2406. void idEntity::BindToBody( idEntity *master, int bodyId, bool orientated ) {
  2407.  
  2408.     if ( !InitBind( master ) ) {
  2409.         return;
  2410.     }
  2411.  
  2412.     if ( bodyId < 0 ) {
  2413.         gameLocal.Warning( "idEntity::BindToBody: body '%d' not found.", bodyId );
  2414.     }
  2415.  
  2416.     PreBind();
  2417.  
  2418.     bindJoint = INVALID_JOINT;
  2419.     bindBody = bodyId;
  2420.     bindMaster = master;
  2421.     fl.bindOrientated = orientated;
  2422.  
  2423.     FinishBind();
  2424.  
  2425.     PostBind();
  2426. }
  2427.  
  2428. /*
  2429. ================
  2430. idEntity::Unbind
  2431. ================
  2432. */
  2433. void idEntity::Unbind( void ) {
  2434.     idEntity *    prev;
  2435.     idEntity *    next;
  2436.     idEntity *    last;
  2437.     idEntity *    ent;
  2438.  
  2439.     // remove any bind constraints from an articulated figure
  2440. // RAVEN BEGIN
  2441. // jnewquist: Use accessor for static class type 
  2442.     if ( IsType( idAFEntity_Base::GetClassType() ) ) {
  2443. // RAVEN END
  2444.         static_cast<idAFEntity_Base *>(this)->RemoveBindConstraints();
  2445.     }
  2446.  
  2447.     if ( !bindMaster ) {
  2448.         return;
  2449.     }
  2450.  
  2451.     if ( !teamMaster ) {
  2452.         // Teammaster already has been freed
  2453.         bindMaster = NULL;
  2454.         return;
  2455.     }
  2456.  
  2457.     PreUnbind();
  2458.  
  2459.     if ( physics ) {
  2460.         physics->SetMaster( NULL, fl.bindOrientated );
  2461.     }
  2462.  
  2463.     // We're still part of a team, so that means I have to extricate myself
  2464.     // and any entities that are bound to me from the old team.
  2465.     // Find the node previous to me in the team
  2466.     prev = teamMaster;
  2467.     for( ent = teamMaster->teamChain; ent && ( ent != this ); ent = ent->teamChain ) {
  2468.         prev = ent;
  2469.     }
  2470.  
  2471.     assert( ent == this ); // If ent is not pointing to this, then something is very wrong.
  2472.  
  2473.     // Find the last node in my team that is bound to me.
  2474.     // Also find the first node not bound to me, if one exists.
  2475.     last = this;
  2476.     for( next = teamChain; next != NULL; next = next->teamChain ) {
  2477.         if ( !next->IsBoundTo( this ) ) {
  2478.             break;
  2479.         }
  2480.  
  2481.         // Tell them I'm now the teamMaster
  2482.         next->teamMaster = this;
  2483.         last = next;
  2484.     }
  2485.  
  2486.     // disconnect the last member of our team from the old team
  2487.     last->teamChain = NULL;
  2488.  
  2489.     // connect up the previous member of the old team to the node that
  2490.     // follow the last node bound to me (if one exists).
  2491.     if ( teamMaster != this ) {
  2492.         prev->teamChain = next;
  2493.         if ( !next && ( teamMaster == prev ) ) {
  2494.             prev->teamMaster = NULL;
  2495.         }
  2496.     } else if ( next ) {
  2497.         // If we were the teamMaster, then the nodes that were not bound to me are now
  2498.         // a disconnected chain.  Make them into their own team.
  2499.         for( ent = next; ent->teamChain != NULL; ent = ent->teamChain ) {
  2500.             ent->teamMaster = next;
  2501.         }
  2502.         next->teamMaster = next;
  2503.     }
  2504.  
  2505.     // If we don't have anyone on our team, then clear the team variables.
  2506.     if ( teamChain ) {
  2507.         // make myself my own team
  2508.         teamMaster = this;
  2509.     } else {
  2510.         // no longer a team
  2511.         teamMaster = NULL;
  2512.     }
  2513.  
  2514.     bindJoint = INVALID_JOINT;
  2515.     bindBody = -1;
  2516.     bindMaster = NULL;
  2517.  
  2518.     PostUnbind();
  2519. }
  2520.  
  2521. /*
  2522. ================
  2523. idEntity::RemoveBinds
  2524. ================
  2525. */
  2526. void idEntity::RemoveBinds( void ) {
  2527.     idEntity *ent;
  2528.     idEntity *next;
  2529.  
  2530.     for( ent = teamChain; ent != NULL; ent = next ) {
  2531.         next = ent->teamChain;
  2532.         if ( ent->bindMaster == this ) {
  2533.             ent->Unbind();
  2534.             ent->PostEventMS( &EV_Remove, 0 );
  2535.             next = teamChain;
  2536.         }
  2537.     }
  2538. }
  2539.  
  2540. /*
  2541. ================
  2542. idEntity::IsBound
  2543. ================
  2544. */
  2545. bool idEntity::IsBound( void ) const {
  2546.     if ( bindMaster ) {
  2547.         return true;
  2548.     }
  2549.     return false;
  2550. }
  2551.  
  2552. /*
  2553. ================
  2554. idEntity::IsBoundTo
  2555. ================
  2556. */
  2557. // RAVEN BEGIN
  2558. // abahr: added const so it can be called from const functions
  2559. bool idEntity::IsBoundTo( const idEntity *master ) const {
  2560. // RAVEN END
  2561.     idEntity *ent;
  2562.  
  2563.     if ( !bindMaster ) {
  2564.         return false;
  2565.     }
  2566.  
  2567.     for ( ent = bindMaster; ent != NULL; ent = ent->bindMaster ) {
  2568.         if ( ent == master ) {
  2569.             return true;
  2570.         }
  2571.     }
  2572.  
  2573.     return false;
  2574. }
  2575.  
  2576. /*
  2577. ================
  2578. idEntity::GetBindMaster
  2579. ================
  2580. */
  2581. idEntity *idEntity::GetBindMaster( void ) const {
  2582.     return bindMaster;
  2583. }
  2584.  
  2585. /*
  2586. ================
  2587. idEntity::GetBindJoint
  2588. ================
  2589. */
  2590. jointHandle_t idEntity::GetBindJoint( void ) const {
  2591.     return bindJoint;
  2592. }
  2593.  
  2594. /*
  2595. ================
  2596. idEntity::GetBindBody
  2597. ================
  2598. */
  2599. int idEntity::GetBindBody( void ) const {
  2600.     return bindBody;
  2601. }
  2602.  
  2603. /*
  2604. ================
  2605. idEntity::GetTeamMaster
  2606. ================
  2607. */
  2608. idEntity *idEntity::GetTeamMaster( void ) const {
  2609.     return teamMaster;
  2610. }
  2611.  
  2612. /*
  2613. ================
  2614. idEntity::GetNextTeamEntity
  2615. ================
  2616. */
  2617. idEntity *idEntity::GetNextTeamEntity( void ) const {
  2618.     return teamChain;
  2619. }
  2620.  
  2621. /*
  2622. =====================
  2623. idEntity::ConvertLocalToWorldTransform
  2624. =====================
  2625. */
  2626. void idEntity::ConvertLocalToWorldTransform( idVec3 &offset, idMat3 &axis ) {
  2627.     UpdateModelTransform();
  2628.  
  2629.     offset = renderEntity.origin + offset * renderEntity.axis;
  2630.     axis *= renderEntity.axis;
  2631. }
  2632.  
  2633. /*
  2634. ================
  2635. idEntity::GetLocalVector
  2636.  
  2637. Takes a vector in worldspace and transforms it into the parent
  2638. object's localspace.
  2639.  
  2640. Note: Does not take origin into acount.  Use getLocalCoordinate to
  2641. convert coordinates.
  2642. ================
  2643. */
  2644. idVec3 idEntity::GetLocalVector( const idVec3 &vec ) const {
  2645.     idVec3    pos;
  2646.  
  2647.     if ( !bindMaster ) {
  2648.         return vec;
  2649.     }
  2650.  
  2651.     idVec3    masterOrigin;
  2652.     idMat3    masterAxis;
  2653.  
  2654.     GetMasterPosition( masterOrigin, masterAxis );
  2655.     masterAxis.ProjectVector( vec, pos );
  2656.  
  2657.     return pos;
  2658. }
  2659.  
  2660. /*
  2661. ================
  2662. idEntity::GetLocalCoordinates
  2663.  
  2664. Takes a vector in world coordinates and transforms it into the parent
  2665. object's local coordinates.
  2666. ================
  2667. */
  2668. idVec3 idEntity::GetLocalCoordinates( const idVec3 &vec ) const {
  2669.     idVec3    pos;
  2670.  
  2671.     if ( !bindMaster ) {
  2672.         return vec;
  2673.     }
  2674.  
  2675.     idVec3    masterOrigin;
  2676.     idMat3    masterAxis;
  2677.  
  2678.     GetMasterPosition( masterOrigin, masterAxis );
  2679.     masterAxis.ProjectVector( vec - masterOrigin, pos );
  2680.  
  2681.     return pos;
  2682. }
  2683.  
  2684. // RAVEN BEGIN
  2685. // kfuller: added method
  2686.  
  2687. /*
  2688. ================
  2689. idEntity::DistanceTo2d
  2690. ================
  2691. */
  2692. float idEntity::DistanceTo2d ( const idVec3& pos ) const {
  2693.     idVec3 pos1;
  2694.     idVec3 pos2;
  2695.     pos1 = pos - (pos * GetPhysics()->GetGravityNormal ( )) * GetPhysics()->GetGravityNormal ( );
  2696.     pos2 = GetPhysics()->GetOrigin ( );
  2697.     pos2 = pos2 - (pos2 * GetPhysics()->GetGravityNormal ( )) * GetPhysics()->GetGravityNormal ( );
  2698.     return (pos2 - pos1).LengthFast ( );
  2699. }
  2700.  
  2701. /*
  2702. ================
  2703. idEntity::GetLocalAngles
  2704. ================
  2705. */
  2706. void idEntity::GetLocalAngles(idAngles &localAng) 
  2707. {
  2708.     idVec3 localVec = GetPhysics()->GetAxis()[0];
  2709.  
  2710.     GetLocalVector(localVec);
  2711.     localAng = localVec.ToAngles();
  2712. }
  2713. // RAVEN END
  2714.  
  2715. /*
  2716. ================
  2717. idEntity::GetWorldVector
  2718.  
  2719. Takes a vector in the parent object's local coordinates and transforms
  2720. it into world coordinates.
  2721.  
  2722. Note: Does not take origin into acount.  Use getWorldCoordinate to
  2723. convert coordinates.
  2724. ================
  2725. */
  2726. idVec3 idEntity::GetWorldVector( const idVec3 &vec ) const {
  2727.     idVec3    pos;
  2728.  
  2729.     if ( !bindMaster ) {
  2730.         return vec;
  2731.     }
  2732.  
  2733.     idVec3    masterOrigin;
  2734.     idMat3    masterAxis;
  2735.  
  2736.     GetMasterPosition( masterOrigin, masterAxis );
  2737.     masterAxis.UnprojectVector( vec, pos );
  2738.  
  2739.     return pos;
  2740. }
  2741.  
  2742. /*
  2743. ================
  2744. idEntity::GetWorldCoordinates
  2745.  
  2746. Takes a vector in the parent object's local coordinates and transforms
  2747. it into world coordinates.
  2748. ================
  2749. */
  2750. idVec3 idEntity::GetWorldCoordinates( const idVec3 &vec ) const {
  2751.     idVec3    pos;
  2752.  
  2753.     if ( !bindMaster ) {
  2754.         return vec;
  2755.     }
  2756.  
  2757.     idVec3    masterOrigin;
  2758.     idMat3    masterAxis;
  2759.  
  2760.     GetMasterPosition( masterOrigin, masterAxis );
  2761.     masterAxis.UnprojectVector( vec, pos );
  2762.     pos += masterOrigin;
  2763.  
  2764.     return pos;
  2765. }
  2766.  
  2767. /*
  2768. ================
  2769. idEntity::GetMasterPosition
  2770. ================
  2771. */
  2772. bool idEntity::GetMasterPosition( idVec3 &masterOrigin, idMat3 &masterAxis ) const {
  2773.     idVec3        localOrigin;
  2774.     idMat3        localAxis;
  2775.     idAnimator    *masterAnimator;
  2776.  
  2777.     if ( bindMaster ) {
  2778.         // if bound to a joint of an animated model
  2779.         if ( bindJoint != INVALID_JOINT ) {
  2780.             masterAnimator = bindMaster->GetAnimator();
  2781.             if ( !masterAnimator ) {
  2782.                 masterOrigin = vec3_origin;
  2783.                 masterAxis = mat3_identity;
  2784.                 return false;
  2785.             } else {
  2786.                 masterAnimator->GetJointTransform( bindJoint, gameLocal.time, masterOrigin, masterAxis );
  2787.                 masterAxis *= bindMaster->renderEntity.axis;
  2788.                 masterOrigin = bindMaster->renderEntity.origin + masterOrigin * bindMaster->renderEntity.axis;
  2789.             }
  2790.         } else if ( bindBody >= 0 && bindMaster->GetPhysics() ) {
  2791.             masterOrigin = bindMaster->GetPhysics()->GetOrigin( bindBody );
  2792.             masterAxis = bindMaster->GetPhysics()->GetAxis( bindBody );
  2793.         } else {
  2794.             masterOrigin = bindMaster->renderEntity.origin;
  2795.             masterAxis = bindMaster->renderEntity.axis;
  2796.         }
  2797.         return true;
  2798.     } else {
  2799.         masterOrigin = vec3_origin;
  2800.         masterAxis = mat3_identity;
  2801.         return false;
  2802.     }
  2803. }
  2804.  
  2805. // RAVEN BEGIN
  2806. // abahr: needed so client get the correct position
  2807. /*
  2808. ================
  2809. idEntity::GetPosition
  2810. ================
  2811. */
  2812. void idEntity::GetPosition( idVec3& origin, idMat3& axis ) const {
  2813.     origin = renderEntity.origin;
  2814.     axis = renderEntity.axis;
  2815. }
  2816. // RAVEN END
  2817.  
  2818. /*
  2819. ================
  2820. idEntity::GetWorldVelocities
  2821. ================
  2822. */
  2823. void idEntity::GetWorldVelocities( idVec3 &linearVelocity, idVec3 &angularVelocity ) const {
  2824.  
  2825.     linearVelocity = physics->GetLinearVelocity();
  2826.     angularVelocity = physics->GetAngularVelocity();
  2827.  
  2828.     if ( bindMaster ) {
  2829.         idVec3 masterOrigin, masterLinearVelocity, masterAngularVelocity;
  2830.         idMat3 masterAxis;
  2831.  
  2832.         // get position of master
  2833.         GetMasterPosition( masterOrigin, masterAxis );
  2834.  
  2835.         // get master velocities
  2836.         bindMaster->GetWorldVelocities( masterLinearVelocity, masterAngularVelocity );
  2837.  
  2838.         // linear velocity relative to master plus master linear and angular velocity
  2839.         linearVelocity = linearVelocity * masterAxis + masterLinearVelocity +
  2840.                                 masterAngularVelocity.Cross( GetPhysics()->GetOrigin() - masterOrigin );
  2841.     }
  2842. }
  2843.  
  2844. /*
  2845. ================
  2846. idEntity::JoinTeam
  2847. ================
  2848. */
  2849. void idEntity::JoinTeam( idEntity *teammember ) {
  2850.     idEntity *ent;
  2851.     idEntity *master;
  2852.     idEntity *prev;
  2853.     idEntity *next;
  2854.  
  2855.     // if we're already on a team, quit it so we can join this one
  2856.     if ( teamMaster && ( teamMaster != this ) ) {
  2857.         QuitTeam();
  2858.     }
  2859.  
  2860.     assert( teammember );
  2861.  
  2862.     if ( teammember == this ) {
  2863.         teamMaster = this;
  2864.         return;
  2865.     }
  2866.  
  2867.     // check if our new team mate is already on a team
  2868.     master = teammember->teamMaster;
  2869.     if ( !master ) {
  2870.         // he's not on a team, so he's the new teamMaster
  2871.         master = teammember;
  2872.         teammember->teamMaster = teammember;
  2873.         teammember->teamChain = this;
  2874.  
  2875.         // make anyone who's bound to me part of the new team
  2876.         for( ent = teamChain; ent != NULL; ent = ent->teamChain ) {
  2877.             ent->teamMaster = master;
  2878.         }
  2879.     } else {
  2880.         // skip past the chain members bound to the entity we're teaming up with
  2881.         prev = teammember;
  2882.         next = teammember->teamChain;
  2883.         if ( bindMaster ) {
  2884.             // if we have a bindMaster, join after any entities bound to the entity
  2885.             // we're joining
  2886.             while( next && next->IsBoundTo( teammember ) ) {
  2887.                 prev = next;
  2888.                 next = next->teamChain;
  2889.             }
  2890.         } else {
  2891.             // if we're not bound to someone, then put us at the end of the team
  2892.             while( next ) {
  2893.                 prev = next;
  2894.                 next = next->teamChain;
  2895.             }
  2896.         }
  2897.  
  2898.         // make anyone who's bound to me part of the new team and
  2899.         // also find the last member of my team
  2900.         for( ent = this; ent->teamChain != NULL; ent = ent->teamChain ) {
  2901.             ent->teamChain->teamMaster = master;
  2902.         }
  2903.  
  2904.         prev->teamChain = this;
  2905.         ent->teamChain = next;
  2906.     }
  2907.  
  2908.     teamMaster = master;
  2909.  
  2910.     // reorder the active entity list 
  2911.     gameLocal.sortTeamMasters = true;
  2912. }
  2913.  
  2914. /*
  2915. ================
  2916. idEntity::QuitTeam
  2917. ================
  2918. */
  2919. void idEntity::QuitTeam( void ) {
  2920.     idEntity *ent;
  2921.  
  2922.     if ( !teamMaster ) {
  2923.         return;
  2924.     }
  2925.  
  2926.     // check if I'm the teamMaster
  2927.     if ( teamMaster == this ) {
  2928.         // do we have more than one teammate?
  2929.         if ( !teamChain->teamChain ) {
  2930.             // no, break up the team
  2931.             teamChain->teamMaster = NULL;
  2932.         } else {
  2933.             // yes, so make the first teammate the teamMaster
  2934.             for( ent = teamChain; ent; ent = ent->teamChain ) {
  2935.                 ent->teamMaster = teamChain;
  2936.             }
  2937.         }
  2938.     } else {
  2939.         assert( teamMaster );
  2940.         assert( teamMaster->teamChain );
  2941.  
  2942.         // find the previous member of the teamChain
  2943.         ent = teamMaster;
  2944.         while( ent->teamChain != this ) {
  2945.             assert( ent->teamChain ); // this should never happen
  2946.             ent = ent->teamChain;
  2947.         }
  2948.  
  2949.         // remove this from the teamChain
  2950.         ent->teamChain = teamChain;
  2951.  
  2952.         // if no one is left on the team, break it up
  2953.         if ( !teamMaster->teamChain ) {
  2954.             teamMaster->teamMaster = NULL;
  2955.         }
  2956.     }
  2957.  
  2958.     teamMaster = NULL;
  2959.     teamChain = NULL;
  2960. }
  2961.  
  2962. /***********************************************************************
  2963.  
  2964.   Physics.
  2965.     
  2966. ***********************************************************************/
  2967.  
  2968. /*
  2969. ================
  2970. idEntity::InitDefaultPhysics
  2971. ================
  2972. */
  2973. void idEntity::InitDefaultPhysics( const idVec3 &origin, const idMat3 &axis ) {
  2974.     const char *temp;
  2975.     idClipModel *clipModel = NULL;
  2976.  
  2977.     // check if a clipmodel key/value pair is set
  2978.     if ( spawnArgs.GetString( "clipmodel", "", &temp ) ) {
  2979. // RAVEN BEGIN
  2980. // mwhitlock: Dynamic memory consolidation
  2981.         RV_PUSH_HEAP_MEM(this);
  2982. // RAVEN END
  2983.         clipModel = new idClipModel( temp );
  2984. // RAVEN BEGIN
  2985. // mwhitlock: Dynamic memory consolidation
  2986.         RV_POP_HEAP();
  2987. // RAVEN END
  2988.     }
  2989.  
  2990.     if ( !spawnArgs.GetBool( "noclipmodel", "0" ) ) {
  2991.  
  2992.         // check if mins/maxs or size key/value pairs are set
  2993.         if ( !clipModel ) {
  2994.             idVec3 size;
  2995.             idBounds bounds;
  2996.             bool setClipModel = false;
  2997.  
  2998.             if ( spawnArgs.GetVector( "mins", NULL, bounds[0] ) &&
  2999.                 spawnArgs.GetVector( "maxs", NULL, bounds[1] ) ) {
  3000.                 setClipModel = true;
  3001.                 if ( bounds[0][0] > bounds[1][0] || bounds[0][1] > bounds[1][1] || bounds[0][2] > bounds[1][2] ) {
  3002.                     gameLocal.Error( "Invalid bounds '%s'-'%s' on entity '%s'", bounds[0].ToString(), bounds[1].ToString(), name.c_str() );
  3003.                 }
  3004.             } else if ( spawnArgs.GetVector( "size", NULL, size ) ) {
  3005.                 if ( ( size.x < 0.0f ) || ( size.y < 0.0f ) || ( size.z < 0.0f ) ) {
  3006.                     gameLocal.Error( "Invalid size '%s' on entity '%s'", size.ToString(), name.c_str() );
  3007.                 }
  3008.                 bounds[0].Set( size.x * -0.5f, size.y * -0.5f, 0.0f );
  3009.                 bounds[1].Set( size.x * 0.5f, size.y * 0.5f, size.z );
  3010.                 setClipModel = true;
  3011.             }
  3012.  
  3013.             if ( setClipModel ) {
  3014.                 int numSides;
  3015.                 idTraceModel trm;
  3016.  
  3017.                 if ( spawnArgs.GetInt( "cylinder", "0", numSides ) && numSides > 0 ) {
  3018.                     trm.SetupCylinder( bounds, numSides < 3 ? 3 : numSides );
  3019.                 } else if ( spawnArgs.GetInt( "cone", "0", numSides ) && numSides > 0 ) {
  3020.                     trm.SetupCone( bounds, numSides < 3 ? 3 : numSides );
  3021. // RAVEN BEGIN
  3022. // bdube: added dodecahedron
  3023.                 } else if ( spawnArgs.GetInt( "dodecahedron", "0", numSides ) && numSides > 0 ) {
  3024.                     trm.SetupDodecahedron ( bounds );
  3025. // RAVEN END
  3026.                 } else {
  3027.                     trm.SetupBox( bounds );
  3028.                 }
  3029. // RAVEN BEGIN
  3030. // mwhitlock: Dynamic memory consolidation
  3031.                 RV_PUSH_HEAP_MEM(this);
  3032. // RAVEN END
  3033.                 clipModel = new idClipModel( trm );
  3034. // RAVEN BEGIN
  3035. // mwhitlock: Dynamic memory consolidation
  3036.                 RV_POP_HEAP();
  3037. // RAVEN END
  3038.             }
  3039.         }
  3040.  
  3041.         // check if the visual model can be used as collision model
  3042.         if ( !clipModel ) {
  3043.             temp = spawnArgs.GetString( "model" );
  3044.             if ( ( temp != NULL ) && ( *temp != 0 ) ) {
  3045. // RAVEN BEGIN
  3046. // jscott:slash problems
  3047.                 idStr canonical = temp;
  3048.                 canonical.BackSlashesToSlashes();
  3049. // RAVEN BEGIN
  3050. // mwhitlock: Dynamic memory consolidation
  3051.                 RV_PUSH_HEAP_MEM(this);
  3052. // RAVEN END
  3053.                 clipModel = new idClipModel();
  3054.                 if ( !clipModel->LoadModel( canonical ) ) {
  3055.                     delete clipModel;
  3056.                     clipModel = NULL;
  3057.                 }
  3058. // RAVEN BEGIN
  3059. // mwhitlock: Dynamic memory consolidation
  3060.                 RV_POP_HEAP();
  3061. // RAVEN END
  3062.             }
  3063.         }
  3064.     }
  3065.  
  3066.     defaultPhysicsObj.SetSelf( this );
  3067.     defaultPhysicsObj.SetClipModel( clipModel, 1.0f );
  3068.     defaultPhysicsObj.SetOrigin( origin );
  3069.     defaultPhysicsObj.SetAxis( axis );
  3070.  
  3071.     physics = &defaultPhysicsObj;
  3072. }
  3073.  
  3074. /*
  3075. ================
  3076. idEntity::SetPhysics
  3077. ================
  3078. */
  3079. void idEntity::SetPhysics( idPhysics *phys ) {
  3080.     // clear any contacts the current physics object has
  3081.     if ( physics ) {
  3082.         physics->ClearContacts();
  3083.     }
  3084.     // set new physics object or set the default physics if NULL
  3085.     if ( phys != NULL ) {
  3086.         defaultPhysicsObj.SetClipModel( NULL, 1.0f );
  3087.         physics = phys;
  3088.         physics->Activate();
  3089.     } else {
  3090.         physics = &defaultPhysicsObj;
  3091.     }
  3092.     physics->UpdateTime( gameLocal.time );
  3093.     physics->SetMaster( bindMaster, fl.bindOrientated );
  3094. }
  3095.  
  3096. /*
  3097. ================
  3098. idEntity::RestorePhysics
  3099. ================
  3100. */
  3101. void idEntity::RestorePhysics( idPhysics *phys ) {
  3102.     assert( phys != NULL );
  3103.     // restore physics pointer
  3104.     physics = phys;
  3105. }
  3106.  
  3107. /*
  3108. ================
  3109. idEntity::RunPhysics
  3110. ================
  3111. */
  3112. bool idEntity::RunPhysics( void ) {
  3113.     int            i, reachedTime, startTime, endTime;
  3114.     idEntity *    part, *blockedPart, *blockingEntity = NULL;
  3115.     trace_t        results;
  3116.     bool        moved;
  3117.  
  3118.     moved = false;
  3119.  
  3120. // RAVEN BEGIN
  3121. // jnewquist: Tag scope and callees to track allocations using "new".
  3122.     MEM_SCOPED_TAG(tag,MA_PHYSICS);
  3123. // RAVEN END
  3124.  
  3125.     // don't run physics if not enabled
  3126.     if ( !( thinkFlags & TH_PHYSICS ) ) {
  3127.         // however do update any animation controllers
  3128.         if ( UpdateAnimationControllers() ) {
  3129.             BecomeActive( TH_ANIMATE );
  3130.         }
  3131. // RAVEN BEGIN
  3132. // kfuller: we want to be able to debug draw the bbox regardless
  3133.         physics->DebugDraw();
  3134. // RAVEN END
  3135.         return false;
  3136.     }
  3137.  
  3138.     // if this entity is a team slave don't do anything because the team master will handle everything
  3139.     if ( teamMaster && teamMaster != this ) {
  3140.         return false;
  3141.     }
  3142.  
  3143.     startTime = gameLocal.previousTime;
  3144.     endTime = gameLocal.time;
  3145.  
  3146.     gameLocal.push.InitSavingPushedEntityPositions();
  3147.     blockedPart = NULL;
  3148.  
  3149.     // save the physics state of the whole team and disable the team for collision detection
  3150.     for ( part = this; part != NULL; part = part->teamChain ) {
  3151.         if ( part->physics ) {
  3152.             if ( !part->fl.solidForTeam ) {
  3153.                 part->physics->DisableClip();
  3154.             }
  3155.             part->physics->SaveState();
  3156.         }
  3157.     }
  3158.  
  3159.     // move the whole team
  3160.     for ( part = this; part != NULL; part = part->teamChain ) {
  3161.  
  3162.         if ( part->physics ) {
  3163.  
  3164.             // run physics
  3165. // RAVEN BEGIN
  3166. // ddynerman: optional pre-prediction
  3167.             moved = part->physics->Evaluate( endTime - startTime + part->predictTime, endTime );
  3168.             part->predictTime = 0;
  3169. // RAVEN END
  3170.  
  3171.             // check if the object is blocked
  3172.             blockingEntity = part->physics->GetBlockingEntity();
  3173.             if ( blockingEntity ) {
  3174.                 blockedPart = part;
  3175.                 break;
  3176.             }
  3177.  
  3178.             // if moved or forced to update the visual position and orientation from the physics
  3179.             if ( moved || part->fl.forcePhysicsUpdate ) {
  3180.                 part->UpdateFromPhysics( false );
  3181.             }
  3182.  
  3183.             // update any animation controllers here so an entity bound
  3184.             // to a joint of this entity gets the correct position
  3185.             if ( part->UpdateAnimationControllers() ) {
  3186.                 part->BecomeActive( TH_ANIMATE );
  3187.             }
  3188.         }
  3189.     }
  3190.  
  3191.     // enable the whole team for collision detection
  3192.     for ( part = this; part != NULL; part = part->teamChain ) {
  3193.         if ( part->physics ) {
  3194.             if ( !part->fl.solidForTeam ) {
  3195.                 part->physics->EnableClip();
  3196.             }
  3197.         }
  3198.     }
  3199.  
  3200.     // cdr: Obstacle Avoidance
  3201.     if (ai_useRVMasterMove.GetBool() && moved && fl.isAIObstacle) {
  3202.         AI_EntityMoved(this);
  3203.     }
  3204.  
  3205.     // if one of the team entities is a pusher and blocked
  3206.     if ( blockedPart ) {
  3207.         // move the parts back to the previous position
  3208.         for ( part = this; part != blockedPart; part = part->teamChain ) {
  3209.  
  3210.             if ( part->physics ) {
  3211.  
  3212.                 // restore the physics state
  3213.                 part->physics->RestoreState();
  3214.  
  3215.                 // move back the visual position and orientation
  3216.                 part->UpdateFromPhysics( true );
  3217.             }
  3218.         }
  3219.         for ( part = this; part != NULL; part = part->teamChain ) {
  3220.             if ( part->physics ) {
  3221.                 // update the physics time without moving
  3222.                 part->physics->UpdateTime( endTime );
  3223.             }
  3224.         }
  3225.  
  3226.         // restore the positions of any pushed entities
  3227.         gameLocal.push.RestorePushedEntityPositions();
  3228.  
  3229.         if ( gameLocal.isClient ) {
  3230.             return false;
  3231.         }
  3232.  
  3233.         // if the master pusher has a "blocked" function, call it
  3234.         Signal( SIG_BLOCKED );
  3235.         ProcessEvent( &EV_TeamBlocked, blockedPart, blockingEntity );
  3236.         // call the blocked function on the blocked part
  3237.         blockedPart->ProcessEvent( &EV_PartBlocked, blockingEntity );
  3238.         return false;
  3239.     }
  3240.  
  3241.     // set pushed
  3242.     for ( i = 0; i < gameLocal.push.GetNumPushedEntities(); i++ ) {
  3243.         idEntity *ent = gameLocal.push.GetPushedEntity( i );
  3244.         ent->physics->SetPushed( endTime - startTime );
  3245.     }
  3246.  
  3247.     if ( gameLocal.isClient ) {
  3248.         return true;
  3249.     }
  3250.  
  3251.     // post reached event if the current time is at or past the end point of the motion
  3252.     for ( part = this; part != NULL; part = part->teamChain ) {
  3253.  
  3254.         if ( part->physics ) {
  3255.  
  3256.             reachedTime = part->physics->GetLinearEndTime();
  3257.             if ( startTime < reachedTime && endTime >= reachedTime ) {
  3258.                 part->ProcessEvent( &EV_ReachedPos );
  3259.             }
  3260.             reachedTime = part->physics->GetAngularEndTime();
  3261.             if ( startTime < reachedTime && endTime >= reachedTime ) {
  3262.                 part->ProcessEvent( &EV_ReachedAng );
  3263.             }
  3264.         }
  3265.     }
  3266.  
  3267.     return true;
  3268. }
  3269.  
  3270. /*
  3271. ================
  3272. idEntity::UpdateFromPhysics
  3273. ================
  3274. */
  3275. void idEntity::UpdateFromPhysics( bool moveBack ) {
  3276.  
  3277. // RAVEN BEGIN
  3278. // jnewquist: Use accessor for static class type 
  3279.     if ( IsType( idActor::GetClassType() ) ) {
  3280. // RAVEN END
  3281.         idActor *actor = static_cast<idActor *>( this );
  3282.  
  3283.         // set master delta angles for actors
  3284.         if ( GetBindMaster() ) {
  3285.             idAngles delta = actor->GetDeltaViewAngles();
  3286.             if ( moveBack ) {
  3287.                 delta.yaw -= static_cast<idPhysics_Actor *>(physics)->GetMasterDeltaYaw();
  3288.             } else {
  3289.                 delta.yaw += static_cast<idPhysics_Actor *>(physics)->GetMasterDeltaYaw();
  3290.             }
  3291.             actor->SetDeltaViewAngles( delta );
  3292.         }
  3293.     }
  3294.  
  3295.     UpdateVisuals();
  3296. }
  3297.  
  3298. /*
  3299. ================
  3300. idEntity::SetOrigin
  3301. ================
  3302. */
  3303. void idEntity::SetOrigin( const idVec3 &org ) {
  3304.  
  3305.     GetPhysics()->SetOrigin( org );
  3306.  
  3307.     UpdateVisuals();
  3308. }
  3309.  
  3310. /*
  3311. ================
  3312. idEntity::SetAxis
  3313. ================
  3314. */
  3315. void idEntity::SetAxis( const idMat3 &axis ) {
  3316.  
  3317. // RAVEN BEGIN
  3318. // jnewquist: Use accessor for static class type 
  3319.     if ( GetPhysics()->IsType( idPhysics_Actor::GetClassType() ) ) {
  3320. // RAVEN END
  3321.         static_cast<idActor *>(this)->viewAxis = axis;
  3322.     } else {
  3323.         GetPhysics()->SetAxis( axis );
  3324.     }
  3325.  
  3326.     UpdateVisuals();
  3327. }
  3328.  
  3329. /*
  3330. ================
  3331. idEntity::SetAngles
  3332. ================
  3333. */
  3334. void idEntity::SetAngles( const idAngles &ang ) {
  3335.     SetAxis( ang.ToMat3() );
  3336. }
  3337.  
  3338. /*
  3339. ================
  3340. idEntity::GetFloorPos
  3341. ================
  3342. */
  3343. bool idEntity::GetFloorPos( float max_dist, idVec3 &floorpos ) const {
  3344.     trace_t result;
  3345.  
  3346.     if ( !GetPhysics()->HasGroundContacts() ) {
  3347.         GetPhysics()->ClipTranslation( result, GetPhysics()->GetGravityNormal() * max_dist, NULL );
  3348.         if ( result.fraction < 1.0f ) {
  3349.             floorpos = result.endpos;
  3350.             return true;
  3351.         } else {
  3352.             floorpos = GetPhysics()->GetOrigin();
  3353.             return false;
  3354.         }
  3355.     } else {
  3356.         floorpos = GetPhysics()->GetOrigin();
  3357.         return true;
  3358.     }
  3359. }
  3360.  
  3361. /*
  3362. ================
  3363. idEntity::GetPhysicsToVisualTransform
  3364. ================
  3365. */
  3366. bool idEntity::GetPhysicsToVisualTransform( idVec3 &origin, idMat3 &axis ) {
  3367.     return false;
  3368. }
  3369.  
  3370. /*
  3371. ================
  3372. idEntity::GetPhysicsToSoundTransform
  3373. ================
  3374. */
  3375. bool idEntity::GetPhysicsToSoundTransform( idVec3 &origin, idMat3 &axis ) {
  3376.     // by default play the sound at the center of the bounding box of the first clip model
  3377.     if ( GetPhysics()->GetNumClipModels() > 0 ) {
  3378.         origin = GetPhysics()->GetBounds().GetCenter();
  3379.         axis.Identity();
  3380.         return true;
  3381.     }
  3382.     return false;
  3383. }
  3384.  
  3385. /*
  3386. ================
  3387. idEntity::Collide
  3388. ================
  3389. */
  3390. bool idEntity::Collide( const trace_t &collision, const idVec3 &velocity ) {
  3391.     // this entity collides with collision.c.entityNum
  3392.     return false;
  3393. }
  3394.  
  3395. /*
  3396. ================
  3397. idEntity::GetImpactInfo
  3398. ================
  3399. */
  3400. void idEntity::GetImpactInfo( idEntity *ent, int id, const idVec3 &point, impactInfo_t *info ) {
  3401.     GetPhysics()->GetImpactInfo( id, point, info );
  3402. }
  3403.  
  3404. /*
  3405. ================
  3406. idEntity::ApplyImpulse
  3407. ================
  3408. */
  3409. void idEntity::ApplyImpulse( idEntity *ent, int id, const idVec3 &point, const idVec3 &impulse, bool splash ) {
  3410.     if( SkipImpulse(ent, id) ) {
  3411.         return;
  3412.     }
  3413.  
  3414.     GetPhysics()->ApplyImpulse( id, point, impulse );
  3415. }
  3416.  
  3417. /*
  3418. ================
  3419. idEntity::AddForce
  3420. ================
  3421. */
  3422. void idEntity::AddForce( idEntity *ent, int id, const idVec3 &point, const idVec3 &force ) {
  3423.     GetPhysics()->AddForce( id, point, force );
  3424. }
  3425.  
  3426. /*
  3427. ================
  3428. idEntity::ActivatePhysics
  3429. ================
  3430. */
  3431. void idEntity::ActivatePhysics( idEntity *ent ) {
  3432.     GetPhysics()->Activate();
  3433. }
  3434.  
  3435. /*
  3436. ================
  3437. idEntity::IsAtRest
  3438. ================
  3439. */
  3440. bool idEntity::IsAtRest( void ) const {
  3441.     return GetPhysics()->IsAtRest();
  3442. }
  3443.  
  3444. /*
  3445. ================
  3446. idEntity::GetRestStartTime
  3447. ================
  3448. */
  3449. int idEntity::GetRestStartTime( void ) const {
  3450.     return GetPhysics()->GetRestStartTime();
  3451. }
  3452.  
  3453. /*
  3454. ================
  3455. idEntity::AddContactEntity
  3456. ================
  3457. */
  3458. void idEntity::AddContactEntity( idEntity *ent ) {
  3459.     GetPhysics()->AddContactEntity( ent );
  3460. }
  3461.  
  3462. /*
  3463. ================
  3464. idEntity::RemoveContactEntity
  3465. ================
  3466. */
  3467. void idEntity::RemoveContactEntity( idEntity *ent ) {
  3468. // RAVEN BEGIN
  3469.     if( GetPhysics() ) {
  3470.  
  3471.         GetPhysics()->RemoveContactEntity( ent );
  3472.     }
  3473. // RAVEN END
  3474. }
  3475.  
  3476.  
  3477.  
  3478. /***********************************************************************
  3479.  
  3480.     Damage
  3481.     
  3482. ***********************************************************************/
  3483.  
  3484. /*
  3485. ============
  3486. idEntity::CanDamage
  3487.  
  3488. Returns true if the inflictor can directly damage the target.  Used for
  3489. explosions and melee attacks.
  3490. ============
  3491. */
  3492. // RAVEN BEGIN
  3493. // bdube: added ignore entity
  3494. bool idEntity::CanDamage( const idVec3 &origin, idVec3 &damagePoint, idEntity* ignoreEnt ) const {
  3495. // RAVEN END
  3496.     idVec3     dest;
  3497.     trace_t    tr;
  3498.     idVec3     midpoint;
  3499.  
  3500.     // use the midpoint of the bounds instead of the origin, because
  3501.     // bmodels may have their origin at 0,0,0
  3502.     midpoint = ( GetPhysics()->GetAbsBounds()[0] + GetPhysics()->GetAbsBounds()[1] ) * 0.5;
  3503.  
  3504.     dest = midpoint;
  3505. // RAVEN BEGIN
  3506. // bdube: added ignore entity
  3507.     gameLocal.TracePoint( this, tr, origin, dest, MASK_SOLID, ignoreEnt );
  3508. // RAVEN END
  3509.     if ( tr.fraction == 1.0 || ( gameLocal.GetTraceEntity( tr ) == this ) ) {
  3510.         damagePoint = tr.endpos;
  3511.         return true;
  3512.     }
  3513.  
  3514.     // this should probably check in the plane of projection, rather than in world coordinate
  3515.     dest = midpoint;
  3516.     dest[0] += 15.0;
  3517.     dest[1] += 15.0;
  3518. // RAVEN BEGIN
  3519. // bdube: added ignore entity
  3520.     gameLocal.TracePoint( this, tr, origin, dest, MASK_SOLID, ignoreEnt );
  3521. // RAVEN ENE
  3522.     if ( tr.fraction == 1.0 || ( gameLocal.GetTraceEntity( tr ) == this ) ) {
  3523.         damagePoint = tr.endpos;
  3524.         return true;
  3525.     }
  3526.  
  3527.     dest = midpoint;
  3528.     dest[0] += 15.0;
  3529.     dest[1] -= 15.0;
  3530. // RAVEN BEGIN
  3531. // bdube: added ignore entity
  3532.     gameLocal.TracePoint( this, tr, origin, dest, MASK_SOLID, ignoreEnt );
  3533. // RAVEN END
  3534.     if ( tr.fraction == 1.0 || ( gameLocal.GetTraceEntity( tr ) == this ) ) {
  3535.         damagePoint = tr.endpos;
  3536.         return true;
  3537.     }
  3538.  
  3539.     dest = midpoint;
  3540.     dest[0] -= 15.0;
  3541.     dest[1] += 15.0;
  3542. // RAVEN BEGIN
  3543. // bdube: added ignore entity
  3544.     gameLocal.TracePoint( this, tr, origin, dest, MASK_SOLID, ignoreEnt );
  3545. // RAVEN END
  3546.     if ( tr.fraction == 1.0 || ( gameLocal.GetTraceEntity( tr ) == this ) ) {
  3547.         damagePoint = tr.endpos;
  3548.         return true;
  3549.     }
  3550.  
  3551.     dest = midpoint;
  3552.     dest[0] -= 15.0;
  3553.     dest[1] -= 15.0;
  3554. // RAVEN BEGIN
  3555. // bdube: added ignore entity
  3556.     gameLocal.TracePoint( this, tr, origin, dest, MASK_SOLID, ignoreEnt );
  3557. // RAVEN EN
  3558.     if ( tr.fraction == 1.0 || ( gameLocal.GetTraceEntity( tr ) == this ) ) {
  3559.         damagePoint = tr.endpos;
  3560.         return true;
  3561.     }
  3562.  
  3563.     dest = midpoint;
  3564.     dest[2] += 15.0;
  3565. // RAVEN BEGIN
  3566. // ddynerman: multiple collision worlds
  3567.     gameLocal.TracePoint( this, tr, origin, dest, MASK_SOLID, NULL );
  3568. // RAVEN END
  3569.     if ( tr.fraction == 1.0 || ( gameLocal.GetTraceEntity( tr ) == this ) ) {
  3570.         damagePoint = tr.endpos;
  3571.         return true;
  3572.     }
  3573.  
  3574.     dest = midpoint;
  3575.     dest[2] -= 15.0;
  3576. // RAVEN BEGIN
  3577. // ddynerman: multiple collision worlds
  3578.     gameLocal.TracePoint( this, tr, origin, dest, MASK_SOLID, NULL );
  3579. // RAVEN END
  3580.     if ( tr.fraction == 1.0 || ( gameLocal.GetTraceEntity( tr ) == this ) ) {
  3581.         damagePoint = tr.endpos;
  3582.         return true;
  3583.     }
  3584.  
  3585.     return false;
  3586. }
  3587.  
  3588. /*
  3589. ================
  3590. idEntity::DamageFeedback
  3591.  
  3592. callback function for when another entity recieved damage from this entity.  damage can be adjusted and returned to the caller.
  3593. ================
  3594. */
  3595. void idEntity::DamageFeedback( idEntity *victim, idEntity *inflictor, int &damage ) {
  3596.     // implemented in subclasses
  3597. }
  3598.  
  3599. /*
  3600. ============
  3601. Damage
  3602.  
  3603. this        entity that is being damaged
  3604. inflictor    entity that is causing the damage
  3605. attacker    entity that caused the inflictor to damage targ
  3606.     example: this=monster, inflictor=rocket, attacker=player
  3607.  
  3608. dir            direction of the attack for knockback in global space
  3609. point        point at which the damage is being inflicted, used for headshots
  3610. damage        amount of damage being inflicted
  3611.  
  3612. inflictor, attacker, dir, and point can be NULL for environmental effects
  3613.  
  3614. ============
  3615. */
  3616. void idEntity::Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir, 
  3617.                       const char *damageDefName, const float damageScale, const int location ) {
  3618.     if ( forwardDamageEnt.IsValid() ) {
  3619.         forwardDamageEnt->Damage( inflictor, attacker, dir, damageDefName, damageScale, location );
  3620.         return;
  3621.     }
  3622.  
  3623.     if ( !fl.takedamage ) {
  3624.         return;
  3625.     }
  3626.  
  3627.     if ( !inflictor ) {
  3628.         inflictor = gameLocal.world;
  3629.     }
  3630.  
  3631.     if ( !attacker ) {
  3632.         attacker = gameLocal.world;
  3633.     }
  3634.  
  3635.     const idDict *damageDef = gameLocal.FindEntityDefDict( damageDefName, false );
  3636.     if ( !damageDef ) {
  3637.         gameLocal.Error( "Unknown damageDef '%s'\n", damageDefName );
  3638.     }
  3639.  
  3640.     int    damage = damageDef->GetInt( "damage" );
  3641.  
  3642.     // inform the attacker that they hit someone
  3643.     attacker->DamageFeedback( this, inflictor, damage );
  3644.     if ( damage ) {
  3645.         // do the damage
  3646.         //jshepard: this is kinda important, no?
  3647.         health -= damage;
  3648.  
  3649.         if ( health <= 0 ) {
  3650.             if ( health < -999 ) {
  3651.                 health = -999;
  3652.             }
  3653.  
  3654.             Killed( inflictor, attacker, damage, dir, location );
  3655.         } else {
  3656.             Pain( inflictor, attacker, damage, dir, location );
  3657.         }
  3658.     }
  3659. }
  3660.  
  3661. /*
  3662. ============
  3663. idEntity::SkipImpulse
  3664. ============
  3665. */
  3666. // RAVEN BEGIN
  3667. // abahr: push stuff
  3668. bool idEntity::SkipImpulse( idEntity *ent, int id ) {
  3669.     return false;//ent == this;
  3670. }
  3671.  
  3672. /*
  3673. ============
  3674. idEntity::ApplyImpulse
  3675. ============
  3676. */
  3677. void idEntity::ApplyImpulse( idEntity* ent, int id, const idVec3& point, const idVec3& dir, const idDict* damageDef ) {
  3678.     ApplyImpulse( ent, id, point, dir * damageDef->GetFloat("push", "5000") );
  3679. }
  3680. // RAVEN END
  3681.  
  3682. /*
  3683. ================
  3684. idEntity::AddDamageEffect
  3685. ================
  3686. */
  3687. void idEntity::AddDamageEffect( const trace_t &collision, const idVec3 &velocity, const char *damageDefName, idEntity* inflictor ) {
  3688.     const char *sound, *decal, *key;
  3689.  
  3690.     const idDeclEntityDef *def = gameLocal.FindEntityDef( damageDefName, false );
  3691. // RAVEN BEGIN
  3692. // bdube: impact_blood is now in the damage def
  3693.     if ( def == NULL || !def->dict.GetBool ( "bleed" ) ) {
  3694. // RAVEN END
  3695.         return;
  3696.     }
  3697.  
  3698.     const char *materialType = gameLocal.sufaceTypeNames[ collision.c.material->GetSurfaceType() ];
  3699.  
  3700.     // start impact sound based on material type
  3701.     key = va( "snd_%s", materialType );
  3702.     sound = spawnArgs.GetString( key );
  3703.     if ( *sound == '\0' ) {
  3704.         sound = def->dict.GetString( key );
  3705.     }
  3706.     if ( *sound != '\0' ) {
  3707.         StartSoundShader( declManager->FindSound( sound ), SND_CHANNEL_BODY, 0, false, NULL );
  3708.     }
  3709.  
  3710.     if ( g_decals.GetBool() ) {
  3711.         // place a wound overlay on the model
  3712.         key = va( "mtr_wound_%s", materialType );
  3713.         decal = spawnArgs.RandomPrefix( key, gameLocal.random );
  3714.         if ( *decal == '\0' ) {
  3715.             decal = def->dict.RandomPrefix( key, gameLocal.random );
  3716.         }
  3717.         if ( *decal != '\0' ) {
  3718.             idVec3 dir = velocity;
  3719.             dir.Normalize();
  3720.             ProjectOverlay( collision.c.point, dir, 20.0f, decal );
  3721.         }
  3722.     }
  3723. }
  3724.  
  3725. /*
  3726. ================
  3727. idEntity::CanPlayImpactEffect
  3728. ================
  3729. */
  3730. bool idEntity::CanPlayImpactEffect ( idEntity* owner, idEntity* ent ) {
  3731.     if( gameLocal.isMultiplayer ) {
  3732.         if( gameLocal.IsTeamGame() && !cvarSystem->GetCVarBool("si_teamDamage") && owner->IsType( idPlayer::GetClassType() ) && ent->IsType( idPlayer::GetClassType() ) && ((idPlayer*)owner)->team == ((idPlayer*)ent)->team ) {
  3733.             return false;         
  3734.         }
  3735.  
  3736.         // default to blood
  3737.         return true;
  3738.     } else {
  3739.         idActor* actorOwner;
  3740.         idAI* aiEnt;
  3741.         actorOwner = dynamic_cast<idActor*>( owner );
  3742.  
  3743.         if ( ent->IsType ( idAFAttachment::GetClassType ( ) ) ) {
  3744.             aiEnt = dynamic_cast<idAI*>( static_cast<idAFAttachment*>( ent )->GetBody ( )  );
  3745.         } else {
  3746.             aiEnt = dynamic_cast<idAI*>( ent );
  3747.         }
  3748.  
  3749.         if ( !actorOwner || !aiEnt ) {
  3750.             return true;
  3751.         }
  3752.  
  3753.         return (actorOwner->team != aiEnt->team);
  3754.     }
  3755. }
  3756.  
  3757. /*
  3758. ============
  3759. idEntity::Pain
  3760.  
  3761. Called whenever an entity recieves damage.  Returns whether the entity responds to the pain.
  3762. This is a virtual function that subclasses are expected to implement.
  3763. ============
  3764. */
  3765. bool idEntity::Pain( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ) {
  3766.     return false;
  3767. }
  3768.  
  3769. /*
  3770. ============
  3771. idEntity::Killed
  3772.  
  3773. Called whenever an entity's health is reduced to 0 or less.
  3774. This is a virtual function that subclasses are expected to implement.
  3775. ============
  3776. */
  3777. void idEntity::Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ) {
  3778. }
  3779.  
  3780. /***********************************************************************
  3781.  
  3782.   Script functions
  3783.     
  3784. ***********************************************************************/
  3785.  
  3786. /*
  3787. ================
  3788. idEntity::ShouldConstructScriptObjectAtSpawn
  3789.  
  3790. Called during idEntity::Spawn to see if it should construct the script object or not.
  3791. Overridden by subclasses that need to spawn the script object themselves.
  3792. ================
  3793. */
  3794. bool idEntity::ShouldConstructScriptObjectAtSpawn( void ) const {
  3795.     return true;
  3796. }
  3797.  
  3798. /*
  3799. ================
  3800. idEntity::ConstructScriptObject
  3801.  
  3802. Called during idEntity::Spawn.  Calls the constructor on the script object.
  3803. Can be overridden by subclasses when a thread doesn't need to be allocated.
  3804. ================
  3805. */
  3806. idThread *idEntity::ConstructScriptObject( void ) {
  3807.     idThread *thread;
  3808.     const function_t *constructor;
  3809.  
  3810.     // init the script object's data
  3811.     scriptObject.ClearObject();
  3812.  
  3813.     // call script object's constructor
  3814.     constructor = scriptObject.GetConstructor();
  3815.     if ( constructor ) {
  3816.         // start a thread that will initialize after Spawn is done being called
  3817. // RAVEN BEGIN
  3818. // mwhitlock: Dynamic memory consolidation
  3819.         RV_PUSH_HEAP_MEM(this);
  3820. // RAVEN END
  3821.         thread = new idThread();
  3822. // RAVEN BEGIN
  3823. // mwhitlock: Dynamic memory consolidation
  3824.         RV_POP_HEAP();
  3825. // RAVEN END
  3826.         thread->SetThreadName( name.c_str() );
  3827.         thread->CallFunction( this, constructor, true );
  3828.         thread->DelayedStart( 0 );
  3829.     } else {
  3830.         thread = NULL;
  3831.     }
  3832.  
  3833.     // clear out the object's memory
  3834.     scriptObject.ClearObject();
  3835.  
  3836.     return thread;
  3837. }
  3838.  
  3839. /*
  3840. ================
  3841. idEntity::DeconstructScriptObject
  3842.  
  3843. Called during idEntity::~idEntity.  Calls the destructor on the script object.
  3844. Can be overridden by subclasses when a thread doesn't need to be allocated.
  3845. Not called during idGameLocal::MapShutdown.
  3846. ================
  3847. */
  3848. void idEntity::DeconstructScriptObject( void ) {
  3849.     idThread        *thread;
  3850.     const function_t *destructor;
  3851.  
  3852.     // don't bother calling the script object's destructor on map shutdown
  3853.     if ( gameLocal.GameState() == GAMESTATE_SHUTDOWN ) {
  3854.         return;
  3855.     }
  3856.  
  3857.     // call script object's destructor
  3858.     destructor = scriptObject.GetDestructor();
  3859.     if ( destructor ) {
  3860.         // start a thread that will run immediately and be destroyed
  3861. // RAVEN BEGIN
  3862. // mwhitlock: Dynamic memory consolidation
  3863.         RV_PUSH_SYS_HEAP_ID(RV_HEAP_ID_TEMPORARY);
  3864. // RAVEN END
  3865.         thread = new idThread();
  3866. // RAVEN BEGIN
  3867. // mwhitlock: Dynamic memory consolidation
  3868.         RV_POP_HEAP();
  3869. // RAVEN END
  3870.         thread->SetThreadName( name.c_str() );
  3871.         thread->CallFunction( this, destructor, true );
  3872.         thread->Execute();
  3873.         delete thread;
  3874.     }
  3875. }
  3876.  
  3877. /*
  3878. ================
  3879. idEntity::HasSignal
  3880. ================
  3881. */
  3882. bool idEntity::HasSignal( signalNum_t signalnum ) const {
  3883.     if ( !signals ) {
  3884.         return false;
  3885.     }
  3886.     assert( ( signalnum >= 0 ) && ( signalnum < NUM_SIGNALS ) );
  3887.     return ( signals->signal[ signalnum ].Num() > 0 );
  3888. }
  3889.  
  3890. /*
  3891. ================
  3892. idEntity::SetSignal
  3893. ================
  3894. */
  3895. void idEntity::SetSignal( signalNum_t signalnum, idThread *thread, const function_t *function ) {
  3896.     int            i;
  3897.     int            num;
  3898.     signal_t    sig;
  3899.     int            threadnum;
  3900.  
  3901.     assert( ( signalnum >= 0 ) && ( signalnum < NUM_SIGNALS ) );
  3902.  
  3903.     if ( !signals ) {
  3904.         signals = new signalList_t;
  3905.     }
  3906.  
  3907.     assert( thread );
  3908.     threadnum = thread->GetThreadNum();
  3909.  
  3910.     num = signals->signal[ signalnum ].Num();
  3911.     for( i = 0; i < num; i++ ) {
  3912.         if ( signals->signal[ signalnum ][ i ].threadnum == threadnum ) {
  3913.             signals->signal[ signalnum ][ i ].function = function;
  3914.             return;
  3915.         }
  3916.     }
  3917.  
  3918.     if ( num >= MAX_SIGNAL_THREADS ) {
  3919.         thread->Error( "Exceeded maximum number of signals per object" );
  3920.     }
  3921.  
  3922.     sig.threadnum = threadnum;
  3923.     sig.function = function;
  3924.     signals->signal[ signalnum ].Append( sig );
  3925. }
  3926.  
  3927. /*
  3928. ================
  3929. idEntity::ClearSignal
  3930. ================
  3931. */
  3932. void idEntity::ClearSignal( idThread *thread, signalNum_t signalnum ) {
  3933.     assert( thread );
  3934.     if ( ( signalnum < 0 ) || ( signalnum >= NUM_SIGNALS ) ) {
  3935.         gameLocal.Error( "Signal out of range" );
  3936.     }
  3937.  
  3938.     if ( !signals ) {
  3939.         return;
  3940.     }
  3941.  
  3942.     signals->signal[ signalnum ].Clear();
  3943. }
  3944.  
  3945. /*
  3946. ================
  3947. idEntity::ClearSignalThread
  3948. ================
  3949. */
  3950. void idEntity::ClearSignalThread( signalNum_t signalnum, idThread *thread ) {
  3951.     int    i;
  3952.     int    num;
  3953.     int    threadnum;
  3954.  
  3955.     assert( thread );
  3956.  
  3957.     if ( ( signalnum < 0 ) || ( signalnum >= NUM_SIGNALS ) ) {
  3958.         gameLocal.Error( "Signal out of range" );
  3959.     }
  3960.  
  3961.     if ( !signals ) {
  3962.         return;
  3963.     }
  3964.  
  3965.     threadnum = thread->GetThreadNum();
  3966.  
  3967.     num = signals->signal[ signalnum ].Num();
  3968.     for( i = 0; i < num; i++ ) {
  3969.         if ( signals->signal[ signalnum ][ i ].threadnum == threadnum ) {
  3970.             signals->signal[ signalnum ].RemoveIndex( i );
  3971.             return;
  3972.         }
  3973.     }
  3974. }
  3975.  
  3976. /*
  3977. ================
  3978. idEntity::Signal
  3979. ================
  3980. */
  3981. void idEntity::Signal( signalNum_t signalnum ) {
  3982.     int            i;
  3983.     int            num;
  3984.     signal_t    sigs[ MAX_SIGNAL_THREADS ];
  3985.     idThread    *thread;
  3986.  
  3987.     assert( ( signalnum >= 0 ) && ( signalnum < NUM_SIGNALS ) );
  3988.  
  3989.     if ( !signals ) {
  3990.         return;
  3991.     }
  3992.  
  3993.     // we copy the signal list since each thread has the potential
  3994.     // to end any of the threads in the list.  By copying the list
  3995.     // we don't have to worry about the list changing as we're
  3996.     // processing it.
  3997.     num = signals->signal[ signalnum ].Num();
  3998.     for( i = 0; i < num; i++ ) {
  3999.         sigs[ i ] = signals->signal[ signalnum ][ i ];
  4000.     }
  4001.  
  4002.     // clear out the signal list so that we don't get into an infinite loop
  4003.     signals->signal[ signalnum ].Clear();
  4004.  
  4005.     for( i = 0; i < num; i++ ) {
  4006.         thread = idThread::GetThread( sigs[ i ].threadnum );
  4007.         if ( thread ) {
  4008.             thread->CallFunction( this, sigs[ i ].function, true );
  4009.             thread->Execute();
  4010.         }
  4011.     }
  4012. }
  4013.  
  4014. /*
  4015. ================
  4016. idEntity::SignalEvent
  4017. ================
  4018. */
  4019. void idEntity::SignalEvent( idThread *thread, signalNum_t signalnum ) {
  4020.     if ( ( signalnum < 0 ) || ( signalnum >= NUM_SIGNALS ) ) {
  4021.         gameLocal.Error( "Signal out of range" );
  4022.     }
  4023.  
  4024.     if ( !signals ) {
  4025.         return;
  4026.     }
  4027.  
  4028.     Signal( signalnum );
  4029. }
  4030.  
  4031. /***********************************************************************
  4032.  
  4033.   Guis.
  4034.     
  4035. ***********************************************************************/
  4036.  
  4037.  
  4038. /*
  4039. ================
  4040. idEntity::TriggerGuis
  4041. ================
  4042. */
  4043. void idEntity::TriggerGuis( void ) {
  4044.     int i;
  4045.     for ( i = 0; i < MAX_RENDERENTITY_GUI; i++ ) {
  4046.         if ( renderEntity.gui[ i ] ) {
  4047.             renderEntity.gui[ i ]->Trigger( gameLocal.time );
  4048.         }
  4049.     }
  4050. }
  4051.  
  4052. /*
  4053. ================
  4054. idEntity::HandleGuiCommands
  4055. ================
  4056. */
  4057. bool idEntity::HandleGuiCommands( idEntity *entityGui, const char *cmds ) {
  4058.     idEntity *targetEnt;
  4059.     bool ret = false;
  4060.     if ( entityGui && cmds && *cmds ) {
  4061.         idLexer src;
  4062.         idToken token, token2, token3, token4;
  4063.         src.LoadMemory( cmds, strlen( cmds ), "guiCommands" );
  4064.         while( 1 ) {
  4065.  
  4066.             if ( !src.ReadToken( &token ) ) {
  4067.                 return ret;
  4068.             }
  4069.  
  4070.             if ( token == ";" ) {
  4071.                 continue;
  4072.             }
  4073.  
  4074.             if ( token.Icmp( "activate" ) == 0 ) {
  4075.                 bool targets = true;
  4076.                 if ( src.ReadToken( &token2 ) ) {
  4077.                     if ( token2 == ";" ) {
  4078.                         src.UnreadToken( &token2 );
  4079.                     } else {
  4080.                         targets = false;
  4081.                     }
  4082.                 }
  4083.  
  4084.                 if ( targets ) {
  4085.                     entityGui->ActivateTargets( this );
  4086.                 } else {
  4087.                     idEntity *ent = gameLocal.FindEntity( token2 );
  4088.                     if ( ent ) {
  4089.                         ent->Signal( SIG_TRIGGER );
  4090.                         ent->PostEventMS( &EV_Activate, 0, this );
  4091.                     }
  4092.                 }
  4093.  
  4094.                 entityGui->renderEntity.shaderParms[ SHADERPARM_MODE ] = 1.0f;
  4095.                 continue;
  4096.             }
  4097.  
  4098.  
  4099.             if ( token.Icmp( "runScript" ) == 0 ) {
  4100.                 if ( src.ReadToken( &token2 ) ) {
  4101.                       while( src.CheckTokenString( "::" ) ) {
  4102.                           idToken token3;
  4103.                           if ( !src.ReadToken( &token3 ) ) {
  4104.                               gameLocal.Error( "Expecting function name following '::' in gui for entity '%s'", entityGui->name.c_str() );
  4105.                           }
  4106.                           token2 += "::" + token3;
  4107.                       }
  4108.                 }
  4109. // RAVEN BEGIN
  4110. // abahr: allow parms to be passed in
  4111. // For some reason the semi colon is used as a delimeter so we need the above code
  4112.                 rvScriptFuncUtility utility;
  4113.                 if( utility.Init(token2) > SFU_ERROR ) {
  4114.                     utility.InsertEntity( entityGui, 0 );
  4115.                     utility.CallFunc( &entityGui->spawnArgs );
  4116.                 }
  4117. // RAVEN END
  4118.                 continue;
  4119.             }
  4120.  
  4121.             if ( token.Icmp("play") == 0 ) {
  4122.                 if ( src.ReadToken( &token2 ) ) {
  4123.                     const idSoundShader *shader = declManager->FindSound(token2);
  4124.                     entityGui->StartSoundShader( shader, SND_CHANNEL_ANY, 0, false, NULL );
  4125.                 }
  4126.                 continue;
  4127.             }
  4128.  
  4129.             if ( token.Icmp( "setkeyval" ) == 0 ) {
  4130.                 if ( src.ReadToken( &token2 ) && src.ReadToken(&token3) && src.ReadToken( &token4 ) ) {
  4131.                     idEntity *ent = gameLocal.FindEntity( token2 );
  4132.                     if ( ent ) {
  4133.                         ent->spawnArgs.Set( token3, token4 );
  4134.                         ent->UpdateChangeableSpawnArgs( NULL );
  4135.                         ent->UpdateVisuals();
  4136.                     }
  4137.                 }
  4138.                 continue;
  4139.             }
  4140.  
  4141.             if ( token.Icmp( "setshaderparm" ) == 0 ) {
  4142.                 if ( src.ReadToken( &token2 ) && src.ReadToken(&token3) ) {
  4143.                     entityGui->SetShaderParm( atoi( token2 ), atof( token3 ) );
  4144.                     entityGui->UpdateVisuals();
  4145.                 }
  4146.                 continue;
  4147.             }
  4148.  
  4149.             if ( token.Icmp("close") == 0 ) {
  4150.                 ret = true;
  4151.                 continue;
  4152.             }
  4153.  
  4154.             // handy for debugging GUI stuff
  4155.             if ( !token.Icmp( "print" ) ) {
  4156.                 idStr msg;
  4157.                 while ( src.ReadToken( &token2 ) ) {
  4158.                     if ( token2 == ";" ) {
  4159.                         src.UnreadToken( &token2 );
  4160.                         break;
  4161.                     }
  4162.                     msg += token2.c_str();
  4163.                 }
  4164.                 common->Printf( "ent gui 0x%x '%s': %s\n", entityNumber, name.c_str(), msg.c_str() );
  4165.                 continue;
  4166.             }
  4167.  
  4168.             // if we get to this point we don't know how to handle it
  4169.             src.UnreadToken(&token);
  4170.             if ( !HandleSingleGuiCommand( entityGui, &src ) ) {
  4171.                 // not handled there see if entity or any of its targets can handle it
  4172.                 // this will only work for one target atm
  4173.                 if ( entityGui->HandleSingleGuiCommand( entityGui, &src ) ) {
  4174.                     continue;
  4175.                 }
  4176.  
  4177.                 int c = entityGui->targets.Num();
  4178.                 int i;
  4179.                 for ( i = 0; i < c; i++) {
  4180.                     targetEnt = entityGui->targets[ i ].GetEntity();
  4181.                     if ( targetEnt && targetEnt->HandleSingleGuiCommand( entityGui, &src ) ) {
  4182.                         break;
  4183.                     }
  4184.                 }
  4185.  
  4186.                 if ( i == c ) {
  4187.                     // not handled
  4188.                     common->DPrintf( "idEntity::HandleGuiCommands: '%s' not handled\n", token.c_str() );
  4189.                     src.ReadToken( &token );
  4190.                 }
  4191.             }
  4192.  
  4193.         }
  4194.     }
  4195.     return ret;
  4196. }
  4197.  
  4198. /*
  4199. ================
  4200. idEntity::HandleSingleGuiCommand
  4201. ================
  4202. */
  4203. bool idEntity::HandleSingleGuiCommand( idEntity *entityGui, idLexer *src ) {
  4204.     return false;
  4205. }
  4206.  
  4207. /***********************************************************************
  4208.  
  4209.   Targets
  4210.     
  4211. ***********************************************************************/
  4212.  
  4213. /*
  4214. ===============
  4215. idEntity::FindTargets
  4216.  
  4217. We have to wait until all entities are spawned
  4218. Used to build lists of targets after the entity is spawned.  Since not all entities
  4219. have been spawned when the entity is created at map load time, we have to wait
  4220. ===============
  4221. */
  4222. void idEntity::FindTargets( void ) {
  4223.     int            i;
  4224.  
  4225.     // targets can be a list of multiple names
  4226.     gameLocal.GetTargets( spawnArgs, targets, "target" );
  4227.  
  4228.     // ensure that we don't target ourselves since that could cause an infinite loop when activating entities
  4229.     for( i = 0; i < targets.Num(); i++ ) {
  4230.         if ( targets[ i ].GetEntity() == this ) {
  4231.             gameLocal.Error( "Entity '%s' is targeting itself", name.c_str() );
  4232.         }
  4233.     }
  4234. }
  4235.  
  4236. /*
  4237. ================
  4238. idEntity::RemoveNullTargets
  4239. ================
  4240. */
  4241. void idEntity::RemoveNullTargets( void ) {
  4242.     int i;
  4243.  
  4244.     for( i = targets.Num() - 1; i >= 0; i-- ) {
  4245.         if ( !targets[ i ].GetEntity() ) {
  4246.             targets.RemoveIndex( i );
  4247.         }
  4248.     }
  4249. }
  4250.  
  4251. /*
  4252. ==============================
  4253. idEntity::ActivateTargets
  4254.  
  4255. "activator" should be set to the entity that initiated the firing.
  4256. ==============================
  4257. */
  4258. void idEntity::ActivateTargets( idEntity *activator ) const {
  4259.     idEntity    *ent;
  4260.     int            i, j;
  4261.     
  4262.     for( i = 0; i < targets.Num(); i++ ) {
  4263.         ent = targets[ i ].GetEntity();
  4264.         if ( !ent ) {
  4265.             continue;
  4266.         }
  4267.         if ( ent->RespondsTo( EV_Activate ) || ent->HasSignal( SIG_TRIGGER ) ) {
  4268.             ent->Signal( SIG_TRIGGER );
  4269.             ent->ProcessEvent( &EV_Activate, activator );
  4270.         }         
  4271.         for ( j = 0; j < MAX_RENDERENTITY_GUI; j++ ) {
  4272.             if ( ent->renderEntity.gui[ j ] ) {
  4273.                 ent->renderEntity.gui[ j ]->Trigger( gameLocal.time );
  4274.             }
  4275.         }
  4276.     }
  4277. }
  4278.  
  4279. // RAVEN BEGIN
  4280. // twhitaker: added (meant to be used from script)
  4281. /*
  4282. ================
  4283. idEntity::AppendTarget
  4284. ================
  4285. */
  4286. int idEntity::AppendTarget( idEntity *appendMe ) {
  4287.  
  4288.     int index = -1;
  4289.     // silently fail if they pass in null
  4290.     if ( appendMe )    {
  4291.         index = targets.Append( appendMe );
  4292.         RemoveNullTargets();
  4293.     }
  4294.     return index;
  4295. }
  4296. /*
  4297. ================
  4298. idEntity::RemoveTarget
  4299. ================
  4300. */
  4301. void idEntity::RemoveTarget( idEntity *removeMe ) {
  4302.  
  4303.     targets.Remove( removeMe );
  4304.     RemoveNullTargets();
  4305. }
  4306. /*
  4307. ================
  4308. idEntity::RemoveTargets
  4309. ================
  4310. */
  4311. void idEntity::RemoveTargets( bool destroyContents ) {
  4312.     if( destroyContents ) {
  4313.         targets.RemoveContents( true );
  4314.     } else {
  4315.         targets.Clear();
  4316.     }
  4317. }
  4318.  
  4319. // jshepard: added
  4320. /*
  4321. ================
  4322. idEntity::UnbindTargets
  4323. ================
  4324. */
  4325. void idEntity::UnbindTargets( idEntity *activator ) const {
  4326.     idEntity    *ent;
  4327.     int            i;
  4328.     
  4329.     for( i = 0; i < targets.Num(); i++ ) {
  4330.         ent = targets[ i ].GetEntity();
  4331.         if ( !ent ) {
  4332.             continue;
  4333.         }
  4334.         ent->Unbind();        
  4335.  
  4336.     }
  4337. }
  4338.  
  4339. // bdube: added
  4340. /*
  4341. ================
  4342. idEntity::Event_SetContents
  4343. ================
  4344. */
  4345. void idEntity::Event_SetContents( int contents ) {
  4346.     GetPhysics()->SetContents( contents );
  4347. }
  4348.  
  4349. /*
  4350. ================
  4351. idEntity::Event_GetLastBlocker
  4352. ================
  4353. */
  4354. void idEntity::Event_GetLastBlocker(idThread *thread) {
  4355.     int    whichEntNum = GetLastBlocker();
  4356.  
  4357.     if (whichEntNum < 0 || whichEntNum == ENTITYNUM_WORLD) {
  4358.         thread->ReturnEntity(this);
  4359.         return;
  4360.     }
  4361.     thread->ReturnEntity(gameLocal.entities[whichEntNum]);
  4362. }
  4363.  
  4364. /*
  4365. ================
  4366. idEntity::ShowSurface
  4367. ================
  4368. */
  4369. void idEntity::ShowSurface ( const char* surface ) {
  4370.     if ( !renderEntity.hModel || !surface || !*surface ) {
  4371.         return;
  4372.     }
  4373.  
  4374.     renderEntity.suppressSurfaceMask &= (~renderEntity.hModel->GetSurfaceMask ( surface ));
  4375. }
  4376.  
  4377. /*
  4378. ================
  4379. idEntity::Event_ShowSurface
  4380. ================
  4381. */
  4382. void idEntity::Event_ShowSurface ( const char* surface ) {
  4383.     ShowSurface ( surface );
  4384. }
  4385.  
  4386. /*
  4387. ================
  4388. idEntity::HideSurface
  4389. ================
  4390. */
  4391. void idEntity::HideSurface ( const char* surface ) {
  4392.     if ( !renderEntity.hModel || !surface || !*surface ) {
  4393.         return;
  4394.     }
  4395.  
  4396.     renderEntity.suppressSurfaceMask |= renderEntity.hModel->GetSurfaceMask ( surface ) ;
  4397. }
  4398.  
  4399. /*
  4400. ================
  4401. idEntity::Event_HideSurface
  4402. ================
  4403. */
  4404. void idEntity::Event_HideSurface ( const char* surface ) {
  4405.     HideSurface ( surface );
  4406. }
  4407.  
  4408. /*
  4409. ================
  4410. idEntity::Event_GuiEvent
  4411. ================
  4412. */
  4413. void idEntity::Event_GuiEvent ( const char* eventName ) {
  4414.     if ( renderEntity.gui[0] ) {
  4415.         renderEntity.gui[0]->HandleNamedEvent ( eventName );
  4416.     } 
  4417. }
  4418.  
  4419. /*
  4420. ================
  4421. idEntity::Event_clearSkin
  4422. ================
  4423. */
  4424. void idEntity::Event_ClearSkin( void ) {
  4425.     ClearSkin();
  4426. }
  4427.  
  4428. /*
  4429. ================
  4430. idEntity::Event_StopAllEffects
  4431. ================
  4432. */
  4433. void idEntity::Event_StopAllEffects ( void ) {
  4434.     StopAllEffects ( );
  4435. }
  4436.  
  4437. /*
  4438. ================
  4439. idEntity::Event_GetHealth
  4440. ================
  4441. */
  4442. void idEntity::Event_GetHealth ( void ) {
  4443.     idThread::ReturnFloat( health );
  4444. }
  4445.  
  4446. // jscott:
  4447. /*
  4448. ================
  4449. idEntity::Event_PlaybackCallback
  4450. ================
  4451. */
  4452. void idEntity::Event_PlaybackCallback ( int type, int changed, int impulse ) {
  4453.     common->Printf( "Playback callback type %d - %d/%d\n", type, changed, impulse );
  4454. }
  4455.  
  4456. // nmckenzie: Check who we're bound to.
  4457. /*
  4458. ================
  4459. idEntity::Event_GetBindMaster
  4460. ================
  4461. */
  4462.  
  4463. void idEntity::Event_GetBindMaster ( void ) {
  4464.     idThread::ReturnEntity( GetBindMaster() );
  4465. }
  4466.  
  4467. /*
  4468. ================
  4469. idEntity::Event_ApplyImpulse
  4470. ================
  4471. */
  4472.  
  4473. void idEntity::Event_ApplyImpulse( idEntity *source, const idVec3 &point, const idVec3 &impulse ){
  4474.     ApplyImpulse( source, 0, point, impulse );
  4475. }
  4476.  
  4477. /*
  4478. ================
  4479. idEntity::Event_PlayEffect
  4480. ================
  4481. */
  4482. void idEntity::Event_PlayEffect( const char *effectName, const char* jointName, bool loop ) {
  4483.     jointHandle_t joint;
  4484.     joint = GetAnimator ( ) ? GetAnimator()->GetJointHandle ( jointName ) : INVALID_JOINT;
  4485.     if ( joint != INVALID_JOINT ) {
  4486.         PlayEffect ( effectName, joint, loop );
  4487.     } else {
  4488.         PlayEffect ( effectName, renderEntity.origin, renderEntity.axis, loop );
  4489.     }    
  4490. }
  4491.  
  4492. /*
  4493. ================
  4494. idEntity::Event_StopEffect
  4495. ================
  4496. */
  4497. void idEntity::Event_StopEffect( const char *effectName ) {
  4498.     StopEffect ( effectName );
  4499. }
  4500.  
  4501. // END RAVEN
  4502.  
  4503. /***********************************************************************
  4504.  
  4505.   Misc.
  4506.     
  4507. ***********************************************************************/
  4508.  
  4509. /*
  4510. ================
  4511. idEntity::Teleport
  4512. ================
  4513. */
  4514. void idEntity::Teleport( const idVec3 &origin, const idAngles &angles, idEntity *destination ) {
  4515.     GetPhysics()->SetOrigin( origin );
  4516.     GetPhysics()->SetAxis( angles.ToMat3() );
  4517.  
  4518.     UpdateVisuals();
  4519. }
  4520.  
  4521. /*
  4522. ============
  4523. idEntity::TouchTriggers
  4524.  
  4525.   Activate all trigger entities touched at the current position.
  4526. ============
  4527. */
  4528. bool idEntity::TouchTriggers( void ) const {
  4529.     int                i, numClipModels, numEntities;
  4530.     idClipModel *    cm;
  4531.     idClipModel *    clipModels[ MAX_GENTITIES ];
  4532.     idEntity *        ent;
  4533.     trace_t            trace;
  4534.  
  4535.     memset( &trace, 0, sizeof( trace ) );
  4536.     trace.endpos = GetPhysics()->GetOrigin();
  4537.     trace.endAxis = GetPhysics()->GetAxis();
  4538.  
  4539. // RAVEN BEGIN
  4540. // ddynerman: multiple clip worlds
  4541.     numClipModels = gameLocal.ClipModelsTouchingBounds( this, GetPhysics()->GetAbsBounds(), CONTENTS_TRIGGER, clipModels, MAX_GENTITIES );
  4542. // RAVEN END
  4543.     numEntities = 0;
  4544.  
  4545.     for ( i = 0; i < numClipModels; i++ ) {
  4546.         cm = clipModels[ i ];
  4547.  
  4548.         // don't touch it if we're the owner
  4549.         if ( cm->GetOwner() == this ) {
  4550.             continue;
  4551.         }
  4552.  
  4553.         ent = cm->GetEntity();
  4554.  
  4555.         if ( !ent->RespondsTo( EV_Touch ) && !ent->HasSignal( SIG_TOUCH ) ) {
  4556.             continue;
  4557.         }
  4558.  
  4559. // RAVEN BEGIN
  4560. // abahr: needed so tram car can has collision model and touch triggers
  4561.         bool useSimpleClip = spawnArgs.GetBool("useSimpleTriggerClip");
  4562.         if ( !useSimpleClip && !GetPhysics()->ClipContents( cm ) ) {
  4563. // RAVEN END
  4564.             continue;
  4565.         }
  4566.  
  4567.         numEntities++;
  4568.  
  4569.         trace.c.contents = cm->GetContents();
  4570.         trace.c.entityNum = cm->GetEntity()->entityNumber;
  4571.         trace.c.id = cm->GetId();
  4572.  
  4573.         ent->Signal( SIG_TOUCH );
  4574.         ent->ProcessEvent( &EV_Touch, this, &trace );
  4575.  
  4576.         if ( !gameLocal.entities[ entityNumber ] ) {
  4577.             gameLocal.Printf( "entity was removed while touching triggers\n" );
  4578.             return true;
  4579.         }
  4580.     }
  4581.  
  4582.     return ( numEntities != 0 );
  4583. }
  4584.  
  4585. /*
  4586. ================
  4587. idEntity::GetSpline
  4588. ================
  4589. */
  4590. idCurve_Spline<idVec3> *idEntity::GetSpline( void ) const {
  4591.     int i, numPoints, t;
  4592.     const idKeyValue *kv;
  4593.     idLexer lex;
  4594.     idVec3 v;
  4595.     idCurve_Spline<idVec3> *spline;
  4596.     const char *curveTag = "curve_";
  4597.  
  4598.     kv = spawnArgs.MatchPrefix( curveTag );
  4599.     if ( !kv ) {
  4600.         return NULL;
  4601.     }
  4602.  
  4603. // RAVEN BEGIN
  4604. // mwhitlock: Dynamic memory consolidation
  4605.     RV_PUSH_HEAP_MEM(this);
  4606. // RAVEN END
  4607.     idStr str = kv->GetKey().Right( kv->GetKey().Length() - strlen( curveTag ) );
  4608.     if ( str.Icmp( "CatmullRomSpline" ) == 0 ) {
  4609.         spline = new idCurve_CatmullRomSpline<idVec3>();
  4610.     } else if ( str.Icmp( "nubs" ) == 0 ) {
  4611.         spline = new idCurve_NonUniformBSpline<idVec3>();
  4612.     } else if ( str.Icmp( "nurbs" ) == 0 ) {
  4613.         spline = new idCurve_NURBS<idVec3>();
  4614.     } else {
  4615.         spline = new idCurve_BSpline<idVec3>();
  4616.     }
  4617. // RAVEN BEGIN
  4618. // mwhitlock: Dynamic memory consolidation
  4619.     RV_POP_HEAP();
  4620. // RAVEN END
  4621.  
  4622.     spline->SetBoundaryType( idCurve_Spline<idVec3>::BT_CLAMPED );
  4623.  
  4624.     lex.LoadMemory( kv->GetValue(), kv->GetValue().Length(), curveTag );
  4625.     numPoints = lex.ParseInt();
  4626.     lex.ExpectTokenString( "(" );
  4627.     for ( t = i = 0; i < numPoints; i++, t += 100 ) {
  4628.         v.x = lex.ParseFloat();
  4629.         v.y = lex.ParseFloat();
  4630.         v.z = lex.ParseFloat();
  4631.         spline->AddValue( t, v );
  4632.     }
  4633.     lex.ExpectTokenString( ")" );
  4634.  
  4635.     return spline;
  4636. }
  4637.  
  4638. /*
  4639. ===============
  4640. idEntity::ShowEditingDialog
  4641. ===============
  4642. */
  4643. void idEntity::ShowEditingDialog( void ) {
  4644. }
  4645.  
  4646. /***********************************************************************
  4647.  
  4648.    Events
  4649.     
  4650. ***********************************************************************/
  4651.  
  4652. /*
  4653. ================
  4654. idEntity::Event_GetName
  4655. ================
  4656. */
  4657. void idEntity::Event_GetName( void ) {
  4658.     idThread::ReturnString( name.c_str() );
  4659. }
  4660.  
  4661. /*
  4662. ================
  4663. idEntity::Event_SetName
  4664. ================
  4665. */
  4666. void idEntity::Event_SetName( const char *newname ) {
  4667.     SetName( newname );
  4668. }
  4669.  
  4670. /*
  4671. ===============
  4672. idEntity::Event_FindTargets
  4673. ===============
  4674. */
  4675. void idEntity::Event_FindTargets( void ) {
  4676.     FindTargets();
  4677. }
  4678.  
  4679. /*
  4680. ============
  4681. idEntity::Event_ActivateTargets
  4682.  
  4683. Activates any entities targeted by this entity.  Mainly used as an
  4684. event to delay activating targets.
  4685. ============
  4686. */
  4687. void idEntity::Event_ActivateTargets( idEntity *activator ) {
  4688.     ActivateTargets( activator );
  4689. }
  4690.  
  4691. // RAVEN BEGIN
  4692. // jshepard: added
  4693. /*
  4694. ============
  4695. idEntity::Event_UnbindTargets
  4696.  
  4697. Unbinds all targets of this entity. Useful to make held or clamped items
  4698. drop when shot, and for breakable walls.
  4699. ============
  4700. */
  4701. void idEntity::Event_UnbindTargets( idEntity *activator ) {
  4702.     UnbindTargets( activator );
  4703. }
  4704.  
  4705. // RAVEN END
  4706.  
  4707.  
  4708. /*
  4709. ================
  4710. idEntity::Event_NumTargets
  4711. ================
  4712. */
  4713. void idEntity::Event_NumTargets( void ) {
  4714.     idThread::ReturnFloat( targets.Num() );
  4715. }
  4716.  
  4717. /*
  4718. ================
  4719. idEntity::Event_GetTarget
  4720. ================
  4721. */
  4722. void idEntity::Event_GetTarget( float index ) {
  4723.     int i;
  4724.  
  4725.     i = ( int )index;
  4726.     if ( ( i < 0 ) || i >= targets.Num() ) {
  4727.         idThread::ReturnEntity( NULL );
  4728.     } else {
  4729.         idThread::ReturnEntity( targets[ i ].GetEntity() );
  4730.     }
  4731. }
  4732.  
  4733. /*
  4734. ================
  4735. idEntity::Event_RandomTarget
  4736. ================
  4737. */
  4738. void idEntity::Event_RandomTarget( const char *ignore ) {
  4739.     int            num;
  4740.     idEntity    *ent;
  4741.     int            i;
  4742.     int            ignoreNum;
  4743.  
  4744.     RemoveNullTargets();
  4745.     if ( !targets.Num() ) {
  4746.         idThread::ReturnEntity( NULL );
  4747.         return;
  4748.     }
  4749.  
  4750.     ignoreNum = -1;
  4751.     if ( ignore && ( ignore[ 0 ] != 0 ) && ( targets.Num() > 1 ) ) {
  4752.         for( i = 0; i < targets.Num(); i++ ) {
  4753.             ent = targets[ i ].GetEntity();
  4754.             if ( ent && ( ent->name == ignore ) ) {
  4755.                 ignoreNum = i;
  4756.                 break;
  4757.             }
  4758.         }
  4759.     }
  4760.  
  4761.     if ( ignoreNum >= 0 ) {
  4762.         num = gameLocal.random.RandomInt( targets.Num() - 1 );
  4763.         if ( num >= ignoreNum ) {
  4764.             num++;
  4765.         }
  4766.     } else {
  4767.         num = gameLocal.random.RandomInt( targets.Num() );
  4768.     }
  4769.  
  4770.     ent = targets[ num ].GetEntity();
  4771.     idThread::ReturnEntity( ent );
  4772. }
  4773.  
  4774. // RAVEN BEGIN
  4775. // abahr: so we can call this from script
  4776. /*
  4777. ================
  4778. idEntity::Event_RemoveNullTargets
  4779. ================
  4780. */
  4781. void idEntity::Event_RemoveNullTargets() {
  4782.     RemoveNullTargets();
  4783. }
  4784.  
  4785. // twhitaker: So targets can be added from script
  4786. /*
  4787. ================
  4788. idEntity::Event_AppendTarget
  4789. ================
  4790. */
  4791. void idEntity::Event_AppendTarget( idEntity *appendMe ) {
  4792.     idThread::ReturnFloat( AppendTarget( appendMe ) );
  4793. }
  4794.  
  4795. /*
  4796. ================
  4797. idEntity::Event_RemoveTarget
  4798. ================
  4799. */
  4800. void idEntity::Event_RemoveTarget( idEntity *removeMe ) {
  4801.     RemoveTarget( removeMe );
  4802. }
  4803.  
  4804. /*
  4805. ================
  4806. idEntity::Event_ClearTargetList
  4807. ================
  4808. */
  4809. void idEntity::Event_ClearTargetList( float destroyContents ) {
  4810.     RemoveTargets( destroyContents != 0.0f );
  4811. }
  4812.  
  4813. /*
  4814. ================
  4815. idEntity::Event_MatchPrefix
  4816. ================
  4817. */
  4818. void idEntity::Event_MatchPrefix( const char *prefix, const char* previousKey ) {
  4819.     const idKeyValue* kv = (previousKey[0]) ? spawnArgs.FindKey(previousKey) : NULL;
  4820.  
  4821.     kv = spawnArgs.MatchPrefix( prefix, kv );
  4822.     if( !kv || !kv->GetValue() ) {
  4823.         idThread::ReturnString( "" );
  4824.         return;
  4825.     }
  4826.  
  4827.     idThread::ReturnString( kv->GetKey() );
  4828. }
  4829.  
  4830. /*
  4831. ================
  4832. idEntity::Event_IsA
  4833. ================
  4834. */
  4835. void idEntity::Event_IsA( const char* entityDefName ) {
  4836.     const idDict* dict = gameLocal.FindEntityDefDict( entityDefName );
  4837.     if( !dict ) {
  4838.         idThread::ReturnFloat( false );
  4839.         return;
  4840.     }
  4841.  
  4842.     idTypeInfo* info = idClass::GetClass( dict->GetString("spawnclass") );
  4843.     if( !info ) {
  4844.         idThread::ReturnFloat( false );
  4845.         return;
  4846.     }
  4847.  
  4848.     idThread::ReturnFloat( IsType(*info) );
  4849. }
  4850.  
  4851. /*
  4852. ================
  4853. idEntity::Event_IsSameTypeAs
  4854. ================
  4855. */
  4856. void idEntity::Event_IsSameTypeAs( const idEntity* ent ) {
  4857.     assert( ent );
  4858.  
  4859.     idThread::ReturnFloat( IsType(ent->Type) );
  4860. }
  4861.  
  4862. // mekberg: allow sethealth on all entities.
  4863. // jshepard: removed clamping
  4864. /*
  4865. ================
  4866. idEntity::Event_SetHealth
  4867. ================
  4868. */
  4869. void idEntity::Event_SetHealth( float newHealth ) {
  4870.     health =  newHealth;
  4871. }
  4872. // RAVEN END
  4873.  
  4874. /*
  4875. ================
  4876. idEntity::Event_BindToJoint
  4877. ================
  4878. */
  4879. void idEntity::Event_BindToJoint( idEntity *master, const char *jointname, float orientated ) {
  4880.     BindToJoint( master, jointname, ( orientated != 0.0f ) );
  4881. }
  4882.  
  4883. /*
  4884. ================
  4885. idEntity::Event_RemoveBinds
  4886. ================
  4887. */
  4888. void idEntity::Event_RemoveBinds( void ) {
  4889.     RemoveBinds();
  4890. }
  4891.  
  4892. /*
  4893. ================
  4894. idEntity::Event_Bind
  4895. ================
  4896. */
  4897. void idEntity::Event_Bind( idEntity *master ) {
  4898.     Bind( master, true );
  4899. }
  4900.  
  4901. /*
  4902. ================
  4903. idEntity::Event_BindPosition
  4904. ================
  4905. */
  4906. void idEntity::Event_BindPosition( idEntity *master ) {
  4907.     Bind( master, false );
  4908. }
  4909.  
  4910. /*
  4911. ================
  4912. idEntity::Event_Unbind
  4913. ================
  4914. */
  4915. void idEntity::Event_Unbind( void ) {
  4916.     Unbind();
  4917. }
  4918.  
  4919. /*
  4920. ================
  4921. idEntity::Event_SpawnBind
  4922. ================
  4923. */
  4924. void idEntity::Event_SpawnBind( void ) {
  4925.     idEntity        *parent;
  4926.     const char        *bind, *joint, *bindanim;
  4927.     jointHandle_t    bindJoint;
  4928.     bool            bindOrientated;
  4929.     int                id;
  4930.     const idAnim    *anim;
  4931.     int                animNum;
  4932.     idAnimator        *parentAnimator;
  4933.     
  4934.     if ( spawnArgs.GetString( "bind", "", &bind ) ) {
  4935.         if ( idStr::Icmp( bind, "worldspawn" ) == 0 ) {
  4936.             //FIXME: Completely unneccessary since the worldspawn is called "world"
  4937.             parent = gameLocal.world;
  4938.         } else {
  4939.             parent = gameLocal.FindEntity( bind );
  4940.         }
  4941.         bindOrientated = spawnArgs.GetBool( "bindOrientated", "1" );
  4942.         if ( parent ) {
  4943.             // bind to a joint of the skeletal model of the parent
  4944.             if ( spawnArgs.GetString( "bindToJoint", "", &joint ) && *joint ) {
  4945.                 parentAnimator = parent->GetAnimator();
  4946.                 if ( !parentAnimator ) {
  4947.                     gameLocal.Error( "Cannot bind to joint '%s' on '%s'.  Entity does not support skeletal models.", joint, name.c_str() );
  4948.                 }
  4949.                 bindJoint = parentAnimator->GetJointHandle( joint );
  4950.                 if ( bindJoint == INVALID_JOINT ) {
  4951.                     gameLocal.Error( "Joint '%s' not found for bind on '%s'", joint, name.c_str() );
  4952.                 }
  4953.  
  4954.                 // bind it relative to a specific anim
  4955.                 if ( ( parent->spawnArgs.GetString( "bindanim", "", &bindanim ) || parent->spawnArgs.GetString( "anim", "", &bindanim ) ) && *bindanim ) {
  4956.                     animNum = parentAnimator->GetAnim( bindanim );
  4957.                     if ( !animNum ) {
  4958.                         gameLocal.Error( "Anim '%s' not found for bind on '%s'", bindanim, name.c_str() );
  4959.                     }
  4960.                     anim = parentAnimator->GetAnim( animNum );
  4961.                     if ( !anim ) {
  4962.                         gameLocal.Error( "Anim '%s' not found for bind on '%s'", bindanim, name.c_str() );
  4963.                     }
  4964.  
  4965.                     // make sure parent's render origin has been set
  4966.                     parent->UpdateModelTransform();
  4967.  
  4968.                     //FIXME: need a BindToJoint that accepts a joint position
  4969.                     parentAnimator->CreateFrame( gameLocal.time, true );
  4970.                     idJointMat *frame = parent->renderEntity.joints;
  4971.                     gameEdit->ANIM_CreateAnimFrame( parentAnimator->ModelHandle(), anim->MD5Anim( 0 ), parent->renderEntity.numJoints, frame, 0, parentAnimator->ModelDef()->GetVisualOffset(), parentAnimator->RemoveOrigin() );
  4972.                     BindToJoint( parent, joint, bindOrientated );
  4973.                     parentAnimator->ForceUpdate();
  4974.                 } else {
  4975.                     BindToJoint( parent, joint, bindOrientated );
  4976.                 }
  4977.             }
  4978.             // bind to a body of the physics object of the parent
  4979.             else if ( spawnArgs.GetInt( "bindToBody", "0", id ) ) {
  4980.                 BindToBody( parent, id, bindOrientated );
  4981.             }
  4982.             // bind to the parent
  4983.             else {
  4984.                 Bind( parent, bindOrientated );
  4985.             }
  4986.         }
  4987.     }
  4988. }
  4989.  
  4990. /*
  4991. ================
  4992. idEntity::Event_SetOwner
  4993. ================
  4994. */
  4995. void idEntity::Event_SetOwner( idEntity *owner ) {
  4996.     int i;
  4997.  
  4998.     for ( i = 0; i < GetPhysics()->GetNumClipModels(); i++ ) {
  4999.         GetPhysics()->GetClipModel( i )->SetOwner( owner );
  5000.     }
  5001. }
  5002.  
  5003. /*
  5004. ================
  5005. idEntity::Event_SetModel
  5006. ================
  5007. */
  5008. void idEntity::Event_SetModel( const char *modelname ) {
  5009.     SetModel( modelname );
  5010. }
  5011.  
  5012. /*
  5013. ================
  5014. idEntity::Event_SetSkin
  5015. ================
  5016. */
  5017. void idEntity::Event_SetSkin( const char *skinname ) {
  5018.     renderEntity.customSkin = declManager->FindSkin( skinname );
  5019.     UpdateVisuals();
  5020. }
  5021.  
  5022. /*
  5023. ================
  5024. idEntity::Event_GetShaderParm
  5025. ================
  5026. */
  5027. void idEntity::Event_GetShaderParm( int parmnum ) {
  5028.     if ( ( parmnum < 0 ) || ( parmnum >= MAX_ENTITY_SHADER_PARMS ) ) {
  5029.         gameLocal.Error( "shader parm index (%d) out of range", parmnum );
  5030.     }
  5031.  
  5032.     idThread::ReturnFloat( renderEntity.shaderParms[ parmnum ] );
  5033. }
  5034.  
  5035. /*
  5036. ================
  5037. idEntity::Event_SetShaderParm
  5038. ================
  5039. */
  5040. void idEntity::Event_SetShaderParm( int parmnum, float value ) {
  5041.     SetShaderParm( parmnum, value );
  5042. }
  5043.  
  5044. /*
  5045. ================
  5046. idEntity::Event_SetShaderParms
  5047. ================
  5048. */
  5049. void idEntity::Event_SetShaderParms( float parm0, float parm1, float parm2, float parm3 ) {
  5050.     renderEntity.shaderParms[ SHADERPARM_RED ]        = parm0;
  5051.     renderEntity.shaderParms[ SHADERPARM_GREEN ]    = parm1;
  5052.     renderEntity.shaderParms[ SHADERPARM_BLUE ]        = parm2;
  5053.     renderEntity.shaderParms[ SHADERPARM_ALPHA ]    = parm3;
  5054.     UpdateVisuals();
  5055. }
  5056.  
  5057.  
  5058. /*
  5059. ================
  5060. idEntity::Event_SetColor
  5061. ================
  5062. */
  5063. void idEntity::Event_SetColor( float red, float green, float blue ) {
  5064.     SetColor( red, green, blue );
  5065. }
  5066.  
  5067. /*
  5068. ================
  5069. idEntity::Event_GetColor
  5070. ================
  5071. */
  5072. void idEntity::Event_GetColor( void ) {
  5073.     idVec3 out;
  5074.  
  5075.     GetColor( out );
  5076.     idThread::ReturnVector( out );
  5077. }
  5078.  
  5079. /*
  5080. ================
  5081. idEntity::Event_IsHidden
  5082. ================
  5083. */
  5084. void idEntity::Event_IsHidden( void ) {
  5085.     idThread::ReturnInt( fl.hidden );
  5086. }
  5087.  
  5088. /*
  5089. ================
  5090. idEntity::Event_Hide
  5091. ================
  5092. */
  5093. void idEntity::Event_Hide( void ) {
  5094.     Hide();
  5095. }
  5096.  
  5097. /*
  5098. ================
  5099. idEntity::Event_Show
  5100. ================
  5101. */
  5102. void idEntity::Event_Show( void ) {
  5103.     Show();
  5104. }
  5105.  
  5106. /*
  5107. ================
  5108. idEntity::Event_CacheSoundShader
  5109. ================
  5110. */
  5111. void idEntity::Event_CacheSoundShader( const char *soundName ) {
  5112.     declManager->FindSound( soundName );
  5113. }
  5114.  
  5115. /*
  5116. ================
  5117. idEntity::Event_StartSoundShader
  5118. ================
  5119. */
  5120. void idEntity::Event_StartSoundShader( const char *soundName, int channel ) {
  5121.     int length;
  5122.  
  5123.     StartSoundShader( declManager->FindSound( soundName ), (s_channelType)channel, 0, false, &length );
  5124.     idThread::ReturnFloat( MS2SEC( length ) );
  5125. }
  5126.  
  5127. /*
  5128. ================
  5129. idEntity::Event_StopSound
  5130. ================
  5131. */
  5132. void idEntity::Event_StopSound( int channel, int netSync ) {
  5133.     StopSound( channel, ( netSync != 0 ) );
  5134. }
  5135.  
  5136. /*
  5137. ================
  5138. idEntity::Event_StartSound 
  5139. ================
  5140. */
  5141. void idEntity::Event_StartSound( const char *soundName, int channel, int netSync ) {
  5142.     int time;
  5143.     
  5144.     StartSound( soundName, ( s_channelType )channel, 0, ( netSync != 0 ), &time );
  5145.     idThread::ReturnFloat( MS2SEC( time ) );
  5146. }
  5147.  
  5148. /*
  5149. ================
  5150. idEntity::Event_FadeSound
  5151. ================
  5152. */
  5153. void idEntity::Event_FadeSound( int channel, float to, float over ) {
  5154. // RAVEN BEGIN
  5155.     idSoundEmitter *emitter = soundSystem->EmitterForIndex( SOUNDWORLD_GAME, refSound.referenceSoundHandle );
  5156.     if ( emitter ) {
  5157.         emitter->FadeSound( channel, to, over );
  5158.     }
  5159. // RAVEN END
  5160. }
  5161.  
  5162. /*
  5163. ================
  5164. idEntity::Event_GetWorldOrigin
  5165. ================
  5166. */
  5167. void idEntity::Event_GetWorldOrigin( void ) {
  5168.     idThread::ReturnVector( GetPhysics()->GetOrigin() );
  5169. }
  5170.  
  5171. /*
  5172. ================
  5173. idEntity::Event_SetWorldOrigin
  5174. ================
  5175. */
  5176. void idEntity::Event_SetWorldOrigin( idVec3 const &org ) {
  5177.     idVec3 neworg = GetLocalCoordinates( org );
  5178.     SetOrigin( neworg );
  5179. }
  5180.  
  5181. /*
  5182. ================
  5183. idEntity::Event_SetOrigin
  5184. ================
  5185. */
  5186. void idEntity::Event_SetOrigin( idVec3 const &org ) {
  5187.     SetOrigin( org );
  5188. }
  5189.  
  5190. /*
  5191. ================
  5192. idEntity::Event_GetOrigin
  5193. ================
  5194. */
  5195. void idEntity::Event_GetOrigin( void ) {
  5196.     idThread::ReturnVector( GetLocalCoordinates( GetPhysics()->GetOrigin() ) );
  5197. }
  5198.  
  5199. /*
  5200. ================
  5201. idEntity::Event_SetAngles
  5202. ================
  5203. */
  5204. void idEntity::Event_SetAngles( idAngles const &ang ) {
  5205.     SetAngles( ang );
  5206. }
  5207.  
  5208. /*
  5209. ================
  5210. idEntity::Event_GetAngles
  5211. ================
  5212. */
  5213. void idEntity::Event_GetAngles( void ) {
  5214.     idAngles ang = GetPhysics()->GetAxis().ToAngles();
  5215.     idThread::ReturnVector( idVec3( ang[0], ang[1], ang[2] ) );
  5216. }
  5217.  
  5218. /*
  5219. ================
  5220. idEntity::Event_SetLinearVelocity
  5221. ================
  5222. */
  5223. void idEntity::Event_SetLinearVelocity( const idVec3 &velocity ) {
  5224.     GetPhysics()->SetLinearVelocity( velocity );
  5225. }
  5226.  
  5227. /*
  5228. ================
  5229. idEntity::Event_GetLinearVelocity
  5230. ================
  5231. */
  5232. void idEntity::Event_GetLinearVelocity( void ) {
  5233.     idThread::ReturnVector( GetPhysics()->GetLinearVelocity() );
  5234. }
  5235.  
  5236. /*
  5237. ================
  5238. idEntity::Event_SetAngularVelocity
  5239. ================
  5240. */
  5241. void idEntity::Event_SetAngularVelocity( const idVec3 &velocity ) {
  5242.     GetPhysics()->SetAngularVelocity( velocity );
  5243. }
  5244.  
  5245. /*
  5246. ================
  5247. idEntity::Event_GetAngularVelocity
  5248. ================
  5249. */
  5250. void idEntity::Event_GetAngularVelocity( void ) {
  5251.     idThread::ReturnVector( GetPhysics()->GetAngularVelocity() );
  5252. }
  5253.  
  5254. /*
  5255. ================
  5256. idEntity::Event_SetSize
  5257. ================
  5258. */
  5259. void idEntity::Event_SetSize( idVec3 const &mins, idVec3 const &maxs ) {
  5260.     GetPhysics()->SetClipBox( idBounds( mins, maxs ), 1.0f );
  5261. }
  5262.  
  5263. /*
  5264. ================
  5265. idEntity::Event_GetSize
  5266. ================
  5267. */
  5268. void idEntity::Event_GetSize( void ) {
  5269.     idBounds bounds;
  5270.  
  5271.     bounds = GetPhysics()->GetBounds();
  5272.     idThread::ReturnVector( bounds[1] - bounds[0] );
  5273. }
  5274.  
  5275. /*
  5276. ================
  5277. idEntity::Event_GetMins
  5278. ================
  5279. */
  5280. void idEntity::Event_GetMins( void ) {
  5281.     idThread::ReturnVector( GetPhysics()->GetBounds()[0] );
  5282. }
  5283.  
  5284. /*
  5285. ================
  5286. idEntity::Event_GetMaxs
  5287. ================
  5288. */
  5289. void idEntity::Event_GetMaxs( void ) {
  5290.     idThread::ReturnVector( GetPhysics()->GetBounds()[1] );
  5291. }
  5292.  
  5293. /*
  5294. ================
  5295. idEntity::Event_Touches
  5296. ================
  5297. */
  5298. void idEntity::Event_Touches( idEntity *ent ) {
  5299.     if ( !ent ) {
  5300.         idThread::ReturnInt( false );
  5301.         return;
  5302.     }
  5303.  
  5304.     const idBounds &myBounds = GetPhysics()->GetAbsBounds();
  5305.     const idBounds &entBounds = ent->GetPhysics()->GetAbsBounds();
  5306.  
  5307.     idThread::ReturnInt( myBounds.IntersectsBounds( entBounds ) );
  5308. }
  5309.  
  5310. /*
  5311. ================
  5312. idEntity::Event_SetGuiParm
  5313. ================
  5314. */
  5315. void idEntity::Event_SetGuiParm( const char *key, const char *val ) {
  5316. // RAVEN BEGIN
  5317. // mekberg: added
  5318.     idStr temp = key;
  5319.     for ( int i = 0; i < MAX_RENDERENTITY_GUI; i++ ) {
  5320.         if ( renderEntity.gui[ i ] ) {
  5321.             if ( idStr::Icmpn( key, "gui_", 4 ) ) {
  5322.                 temp.Insert( "gui_", 0 );    
  5323.             }
  5324.             spawnArgs.Set( temp.c_str(), val );
  5325. // RAVEN END
  5326.             
  5327.             renderEntity.gui[ i ]->SetStateString( key, val );
  5328.             renderEntity.gui[ i ]->StateChanged( gameLocal.time );
  5329.         }
  5330.     }
  5331. }
  5332.  
  5333. /*
  5334. ================
  5335. idEntity::Event_SetGuiParm
  5336. ================
  5337. */
  5338. void idEntity::Event_SetGuiFloat( const char *key, float f ) {
  5339.     for ( int i = 0; i < MAX_RENDERENTITY_GUI; i++ ) {
  5340.         if ( renderEntity.gui[ i ] ) {
  5341.             renderEntity.gui[ i ]->SetStateString( key, va( "%f", f ) );
  5342.             renderEntity.gui[ i ]->StateChanged( gameLocal.time );
  5343.         }
  5344.     }
  5345. }
  5346.  
  5347. /*
  5348. ================
  5349. idEntity::Event_GetNextKey
  5350. ================
  5351. */
  5352. void idEntity::Event_GetNextKey( const char *prefix, const char *lastMatch ) {
  5353.     const idKeyValue *kv;
  5354.     const idKeyValue *previous;
  5355.  
  5356.     if ( *lastMatch ) {
  5357.         previous = spawnArgs.FindKey( lastMatch );
  5358.     } else {
  5359.         previous = NULL;
  5360.     }
  5361.  
  5362.     kv = spawnArgs.MatchPrefix( prefix, previous );
  5363.     if ( !kv ) {
  5364.         idThread::ReturnString( "" );
  5365.     } else {
  5366.         idThread::ReturnString( kv->GetKey() );
  5367.     }
  5368. }
  5369.  
  5370. /*
  5371. ================
  5372. idEntity::Event_SetKey
  5373. ================
  5374. */
  5375. void idEntity::Event_SetKey( const char *key, const char *value ) {
  5376.     spawnArgs.Set( key, value );
  5377. }
  5378.  
  5379. /*
  5380. ================
  5381. idEntity::Event_GetKey
  5382. ================
  5383. */
  5384. void idEntity::Event_GetKey( const char *key ) {
  5385.     const char *value;
  5386.  
  5387.     spawnArgs.GetString( key, "", &value );
  5388.     idThread::ReturnString( value );
  5389. }
  5390.  
  5391. /*
  5392. ================
  5393. idEntity::Event_GetIntKey
  5394. ================
  5395. */
  5396. void idEntity::Event_GetIntKey( const char *key ) {
  5397.     int value;
  5398.  
  5399.     spawnArgs.GetInt( key, "0", value );
  5400.  
  5401.     // scripts only support floats
  5402.     idThread::ReturnFloat( value );
  5403. }
  5404.  
  5405. /*
  5406. ================
  5407. idEntity::Event_GetFloatKey
  5408. ================
  5409. */
  5410. void idEntity::Event_GetFloatKey( const char *key ) {
  5411.     float value;
  5412.  
  5413.     spawnArgs.GetFloat( key, "0", value );
  5414.     idThread::ReturnFloat( value );
  5415. }
  5416.  
  5417. /*
  5418. ================
  5419. idEntity::Event_GetVectorKey
  5420. ================
  5421. */
  5422. void idEntity::Event_GetVectorKey( const char *key ) {
  5423.     idVec3 value;
  5424.  
  5425.     spawnArgs.GetVector( key, "0 0 0", value );
  5426.     idThread::ReturnVector( value );
  5427. }
  5428.  
  5429. /*
  5430. ================
  5431. idEntity::Event_GetEntityKey
  5432. ================
  5433. */
  5434. void idEntity::Event_GetEntityKey( const char *key ) {
  5435.     idEntity *ent;
  5436.     const char *entname;
  5437.  
  5438.     if ( !spawnArgs.GetString( key, NULL, &entname ) ) {
  5439.         idThread::ReturnEntity( NULL );
  5440.         return;
  5441.     }
  5442.  
  5443.     ent = gameLocal.FindEntity( entname );
  5444.     if ( !ent ) {
  5445.         gameLocal.Warning( "Couldn't find entity '%s' specified in '%s' key in entity '%s'", entname, key, name.c_str() );
  5446.     }
  5447.  
  5448.     idThread::ReturnEntity( ent );
  5449. }
  5450.  
  5451. /*
  5452. ================
  5453. idEntity::Event_RestorePosition
  5454. ================
  5455. */
  5456. void idEntity::Event_RestorePosition( void ) {
  5457.     idVec3        org;
  5458.     idAngles    angles;
  5459.     idMat3        axis;
  5460.     idEntity *    part;
  5461.  
  5462.     spawnArgs.GetVector( "origin", "0 0 0", org );
  5463.  
  5464.     // get the rotation matrix in either full form, or single angle form
  5465.     if ( spawnArgs.GetMatrix( "rotation", "1 0 0 0 1 0 0 0 1", axis ) ) {
  5466.         angles = axis.ToAngles();
  5467.     } else {
  5468.            angles[ 0 ] = 0;
  5469.            angles[ 1 ] = spawnArgs.GetFloat( "angle" );
  5470.            angles[ 2 ] = 0;
  5471.     }
  5472.  
  5473.     Teleport( org, angles, NULL );
  5474.  
  5475.     for ( part = teamChain; part != NULL; part = part->teamChain ) {
  5476.         if ( part->bindMaster != this ) {
  5477.             continue;
  5478.         }
  5479. // RAVEN BEGIN
  5480. // jnewquist: Use accessor for static class type 
  5481.         if ( part->GetPhysics()->IsType( idPhysics_Parametric::GetClassType() ) ) {
  5482.             if ( static_cast<idPhysics_Parametric *>(part->GetPhysics())->IsPusher() ) {
  5483.                 gameLocal.Warning( "teleported '%s' which has the pushing mover '%s' bound to it\n", GetName(), part->GetName() );
  5484.             }
  5485.         } else if ( part->GetPhysics()->IsType( idPhysics_AF::GetClassType() ) ) {
  5486. // RAVEN END
  5487.             gameLocal.Warning( "teleported '%s' which has the articulated figure '%s' bound to it\n", GetName(), part->GetName() );
  5488.         }
  5489.     }
  5490. }
  5491.  
  5492. /*
  5493. ================
  5494. idEntity::Event_UpdateCameraTarget
  5495. ================
  5496. */
  5497. void idEntity::Event_UpdateCameraTarget( void ) {
  5498.     const char *target;
  5499.     const idKeyValue *kv;
  5500.     idVec3 dir;
  5501.  
  5502.     target = spawnArgs.GetString( "cameraTarget" );
  5503.  
  5504.     cameraTarget = gameLocal.FindEntity( target );
  5505.  
  5506.     if ( cameraTarget ) {
  5507.         kv = cameraTarget->spawnArgs.MatchPrefix( "target", NULL );
  5508.         while( kv ) {
  5509.             idEntity *ent = gameLocal.FindEntity( kv->GetValue() );
  5510.             if ( ent && idStr::Icmp( ent->GetEntityDefName(), "target_null" ) == 0) {
  5511.                 dir = ent->GetPhysics()->GetOrigin() - cameraTarget->GetPhysics()->GetOrigin();
  5512.                 dir.Normalize();
  5513.                 cameraTarget->SetAxis( dir.ToMat3() );
  5514. // RAVEN BEGIN
  5515. // rjohnson: if you have a func_cameraview pointing to an info_null via "cameratarget" and
  5516. //             you have a func_static pointing to the func_cameraview via a "cameratarget" then
  5517. //             the func_static evaluates 'target' to the func_cameraview and its target it the info null
  5518. //             the SexAxis() is then applied to the the func_static rather than the func_cameraview
  5519. //                SetAxis(dir.ToMat3());
  5520. // RAVEN END
  5521.                 break;                        
  5522.             }
  5523.             kv = cameraTarget->spawnArgs.MatchPrefix( "target", kv );
  5524.         }
  5525.     }
  5526.     UpdateVisuals();
  5527. }
  5528.  
  5529. /*
  5530. ================
  5531. idEntity::Event_DistanceTo
  5532. ================
  5533. */
  5534. void idEntity::Event_DistanceTo( idEntity *ent ) {
  5535.     if ( !ent ) {
  5536.         // just say it's really far away
  5537.         idThread::ReturnFloat( MAX_WORLD_SIZE );
  5538.     } else {
  5539.         float dist = ( GetPhysics()->GetOrigin() - ent->GetPhysics()->GetOrigin() ).LengthFast();
  5540.         idThread::ReturnFloat( dist );
  5541.     }
  5542. }
  5543.  
  5544. /*
  5545. ================
  5546. idEntity::Event_DistanceToPoint
  5547. ================
  5548. */
  5549. void idEntity::Event_DistanceToPoint( const idVec3 &point ) {
  5550.     float dist = ( GetPhysics()->GetOrigin() - point ).LengthFast();
  5551.     idThread::ReturnFloat( dist );
  5552. }
  5553.  
  5554. /*
  5555. ================
  5556. idEntity::Event_StartFx
  5557. ================
  5558. */
  5559. void idEntity::Event_StartFx( const char *fx ) {
  5560. // RAVEN BEGIN
  5561. // bdube: not used
  5562. //    idEntityFx::StartFx( fx, NULL, NULL, this, true );
  5563. // RAVEN END
  5564. }
  5565.  
  5566. /*
  5567. ================
  5568. idEntity::Event_WaitFrame
  5569. ================
  5570. */
  5571. void idEntity::Event_WaitFrame( void ) {
  5572.     idThread *thread;
  5573.     
  5574.     thread = idThread::CurrentThread();
  5575.     if ( thread ) {
  5576.         thread->WaitFrame();
  5577.     }
  5578. }
  5579.  
  5580. /*
  5581. =====================
  5582. idEntity::Event_Wait
  5583. =====================
  5584. */
  5585. void idEntity::Event_Wait( float time ) {
  5586.     idThread *thread = idThread::CurrentThread();
  5587.  
  5588.     if ( !thread ) {
  5589.         gameLocal.Error( "Event 'wait' called from outside thread" );
  5590.     }
  5591.  
  5592.     thread->WaitSec( time );
  5593. }
  5594.  
  5595. /*
  5596. =====================
  5597. idEntity::Event_HasFunction
  5598. =====================
  5599. */
  5600. void idEntity::Event_HasFunction( const char *name ) {
  5601.     const function_t *func;
  5602.  
  5603.     func = scriptObject.GetFunction( name );
  5604.     if ( func ) {
  5605.         idThread::ReturnInt( true );
  5606.     } else {
  5607.         idThread::ReturnInt( false );
  5608.     }
  5609. }
  5610.  
  5611. /*
  5612. =====================
  5613. idEntity::Event_CallFunction
  5614. =====================
  5615. */
  5616. void idEntity::Event_CallFunction( const char *funcname ) {
  5617. // RAVEN BEGIN
  5618. // bdube: states
  5619.     stateParms_t parms = {0};
  5620.     if ( ProcessState ( funcname, parms ) != SRESULT_ERROR ) {
  5621.         return;
  5622.     }
  5623.     gameLocal.CallObjectFrameCommand ( this, funcname );
  5624. // RAVEN END
  5625. }
  5626.  
  5627. /*
  5628. ================
  5629. idEntity::Event_SetNeverDormant
  5630. ================
  5631. */
  5632. void idEntity::Event_SetNeverDormant( int enable ) {
  5633.     fl.neverDormant    = ( enable != 0 );
  5634.     dormantStart = 0;
  5635. }
  5636.  
  5637. /***********************************************************************
  5638.  
  5639.    Network
  5640.     
  5641. ***********************************************************************/
  5642.  
  5643. /*
  5644. ================
  5645. idEntity::ClientPredictionThink
  5646. ================
  5647. */
  5648. void idEntity::ClientPredictionThink( void ) {
  5649.     RunPhysics();
  5650.     Present();
  5651. }
  5652.  
  5653. /*
  5654. ================
  5655. idEntity::WriteBindToSnapshot
  5656. ================
  5657. */
  5658. void idEntity::WriteBindToSnapshot( idBitMsgDelta &msg ) const {
  5659.     int bindInfo;
  5660.  
  5661.     if ( bindMaster ) {
  5662.         bindInfo = bindMaster->entityNumber;
  5663.         bindInfo |= ( fl.bindOrientated & 1 ) << GENTITYNUM_BITS;
  5664.         if ( bindJoint != INVALID_JOINT ) {
  5665.             bindInfo |= 1 << ( GENTITYNUM_BITS + 1 );
  5666.             bindInfo |= bindJoint << ( 3 + GENTITYNUM_BITS );
  5667.         } else if ( bindBody != -1 ) {
  5668.             bindInfo |= 2 << ( GENTITYNUM_BITS + 1 );
  5669.             bindInfo |= bindBody << ( 3 + GENTITYNUM_BITS );
  5670.         }
  5671.     } else {
  5672.         bindInfo = ENTITYNUM_NONE;
  5673.     }
  5674.     msg.WriteBits( bindInfo, GENTITYNUM_BITS + 3 + 9 );
  5675. }
  5676.  
  5677. /*
  5678. ================
  5679. idEntity::ReadBindFromSnapshot
  5680. ================
  5681. */
  5682. void idEntity::ReadBindFromSnapshot( const idBitMsgDelta &msg ) {
  5683.     int bindInfo, bindEntityNum, bindPos;
  5684.     bool bindOrientated;
  5685.     idEntity *master;
  5686.  
  5687.     bindInfo = msg.ReadBits( GENTITYNUM_BITS + 3 + 9 );
  5688.     bindEntityNum = bindInfo & ( ( 1 << GENTITYNUM_BITS ) - 1 );
  5689.  
  5690.     if ( bindEntityNum != ENTITYNUM_NONE ) {
  5691.         master = gameLocal.entities[ bindEntityNum ];
  5692.  
  5693.         if ( master != bindMaster ) {
  5694.             if ( bindMaster ) {
  5695.                 Unbind();
  5696.             }
  5697.             bindOrientated = ( bindInfo >> GENTITYNUM_BITS ) & 1;
  5698.             bindPos = ( bindInfo >> ( GENTITYNUM_BITS + 3 ) ) & 3;
  5699.             switch( ( bindInfo >> ( GENTITYNUM_BITS + 1 ) ) & 3 ) {
  5700.                 case 1: {
  5701.                     BindToJoint( master, (jointHandle_t) bindPos, bindOrientated );
  5702.                     break;
  5703.                 }
  5704.                 case 2: {
  5705.                     BindToBody( master, bindPos, bindOrientated );
  5706.                     break;
  5707.                 }
  5708.                 default: {
  5709.                     Bind( master, bindOrientated );
  5710.                     break;
  5711.                 }
  5712.             }
  5713.         }
  5714.     }
  5715. }
  5716.  
  5717. /*
  5718. ================
  5719. idEntity::WriteColorToSnapshot
  5720. ================
  5721. */
  5722. void idEntity::WriteColorToSnapshot( idBitMsgDelta &msg ) const {
  5723.     idVec4 color;
  5724.  
  5725.     color[0] = renderEntity.shaderParms[ SHADERPARM_RED ];
  5726.     color[1] = renderEntity.shaderParms[ SHADERPARM_GREEN ];
  5727.     color[2] = renderEntity.shaderParms[ SHADERPARM_BLUE ];
  5728.     color[3] = renderEntity.shaderParms[ SHADERPARM_ALPHA ];
  5729.     msg.WriteLong( PackColor( color ) );
  5730. }
  5731.  
  5732. /*
  5733. ================
  5734. idEntity::ReadColorFromSnapshot
  5735. ================
  5736. */
  5737. void idEntity::ReadColorFromSnapshot( const idBitMsgDelta &msg ) {
  5738.     idVec4 color;
  5739.  
  5740.     UnpackColor( msg.ReadLong(), color );
  5741.     renderEntity.shaderParms[ SHADERPARM_RED ] = color[0];
  5742.     renderEntity.shaderParms[ SHADERPARM_GREEN ] = color[1];
  5743.     renderEntity.shaderParms[ SHADERPARM_BLUE ] = color[2];
  5744.     renderEntity.shaderParms[ SHADERPARM_ALPHA ] = color[3];
  5745. }
  5746.  
  5747. /*
  5748. ================
  5749. idEntity::WriteGUIToSnapshot
  5750. ================
  5751. */
  5752. void idEntity::WriteGUIToSnapshot( idBitMsgDelta &msg ) const {
  5753.     // no need to loop over MAX_RENDERENTITY_GUI at this time
  5754.     if ( renderEntity.gui[ 0 ] ) {
  5755.         msg.WriteByte( renderEntity.gui[ 0 ]->State().GetInt( "networkState" ) );
  5756.     } else {
  5757.         msg.WriteByte( 0 );
  5758.     }
  5759. }
  5760.  
  5761. /*
  5762. ================
  5763. idEntity::ReadGUIFromSnapshot
  5764. ================
  5765. */
  5766. void idEntity::ReadGUIFromSnapshot( const idBitMsgDelta &msg ) {
  5767.     int state;
  5768.     idUserInterface *gui;
  5769.     state = msg.ReadByte( );
  5770.     gui = renderEntity.gui[ 0 ];
  5771.     if ( gui && state != mpGUIState ) {
  5772.         mpGUIState = state;
  5773.         gui->SetStateInt( "networkState", state );
  5774.         gui->HandleNamedEvent( "networkState" );
  5775.     }
  5776. }
  5777.  
  5778. /*
  5779. ================
  5780. idEntity::WriteToSnapshot
  5781. ================
  5782. */
  5783. void idEntity::WriteToSnapshot( idBitMsgDelta &msg ) const {
  5784. }
  5785.  
  5786. /*
  5787. ================
  5788. idEntity::ReadFromSnapshot
  5789. ================
  5790. */
  5791. void idEntity::ReadFromSnapshot( const idBitMsgDelta &msg ) {
  5792. }
  5793.  
  5794. /*
  5795. ================
  5796. idEntity::ServerSendEvent
  5797.  
  5798.    Saved events are also sent to any client that connects late so all clients
  5799.    always receive the events nomatter what time they join the game.
  5800.    ================
  5801.    */
  5802. void idEntity::ServerSendEvent( int eventId, const idBitMsg *msg, bool saveEvent, int excludeClient ) const {
  5803.     idBitMsg    outMsg;
  5804.     byte        msgBuf[MAX_GAME_MESSAGE_SIZE];
  5805.  
  5806.     if ( !gameLocal.isServer ) {
  5807.         return;
  5808.     }
  5809.  
  5810.     // prevent dupe events caused by frame re-runs
  5811.     if ( !gameLocal.isNewFrame ) {
  5812.         return;
  5813.     }
  5814.  
  5815.     outMsg.Init( msgBuf, sizeof( msgBuf ) );
  5816.     outMsg.BeginWriting();
  5817.     outMsg.WriteByte( GAME_RELIABLE_MESSAGE_EVENT );    
  5818.     outMsg.WriteBits( gameLocal.GetSpawnId( this ), 32 );
  5819.     outMsg.WriteByte( eventId );
  5820.     outMsg.WriteLong( gameLocal.time );
  5821.     if ( msg ) {
  5822.         outMsg.WriteBits( msg->GetSize(), idMath::BitsForInteger( MAX_EVENT_PARAM_SIZE ) );
  5823.         outMsg.WriteData( msg->GetData(), msg->GetSize() );
  5824.     } else {
  5825.         outMsg.WriteBits( 0, idMath::BitsForInteger( MAX_EVENT_PARAM_SIZE ) );
  5826.     }
  5827.  
  5828.     networkSystem->ServerSendReliableMessageExcluding( excludeClient, outMsg );
  5829.  
  5830.     if ( saveEvent ) {
  5831.         gameLocal.Error( "Unsupported saveEvent == true in idEntity::ServerSendEvent" );
  5832.     }
  5833. }
  5834.  
  5835. /*
  5836. ================
  5837. idEntity::ServerSendInstanceEvent
  5838. ================
  5839. */
  5840. void idEntity::ServerSendInstanceEvent( int eventId, const idBitMsg *msg, bool saveEvent, int excludeClient ) const {
  5841.     idBitMsg    outMsg;
  5842.     byte        msgBuf[MAX_GAME_MESSAGE_SIZE];
  5843.  
  5844.     if ( !gameLocal.isServer ) {
  5845.         return;
  5846.     }
  5847.  
  5848.     // prevent dupe events caused by frame re-runs
  5849.     if ( !gameLocal.isNewFrame ) {
  5850.         return;
  5851.     }
  5852.  
  5853.     outMsg.Init( msgBuf, sizeof( msgBuf ) );
  5854.     outMsg.BeginWriting();
  5855.     outMsg.WriteByte( GAME_RELIABLE_MESSAGE_EVENT );    
  5856.     outMsg.WriteBits( gameLocal.GetSpawnId( this ), 32 );
  5857.     outMsg.WriteByte( eventId );
  5858.     outMsg.WriteLong( gameLocal.time );
  5859.     if ( msg ) {
  5860.         outMsg.WriteBits( msg->GetSize(), idMath::BitsForInteger( MAX_EVENT_PARAM_SIZE ) );
  5861.         outMsg.WriteData( msg->GetData(), msg->GetSize() );
  5862.     } else {
  5863.         outMsg.WriteBits( 0, idMath::BitsForInteger( MAX_EVENT_PARAM_SIZE ) );
  5864.     }
  5865.  
  5866.     gameLocal.ServerSendInstanceReliableMessageExcluding( this, excludeClient, outMsg );
  5867.  
  5868.     if ( saveEvent ) {
  5869.         gameLocal.Error( "Unsupported saveEvent == true in idEntity::ServerSendEvent" );
  5870.     }
  5871. }
  5872.  
  5873. /*
  5874. ================
  5875. idEntity::ClientSendEvent
  5876. ================
  5877. */
  5878. void idEntity::ClientSendEvent( int eventId, const idBitMsg *msg ) const {
  5879.     idBitMsg    outMsg;
  5880.     byte        msgBuf[MAX_GAME_MESSAGE_SIZE];
  5881.  
  5882.     if ( !gameLocal.isClient ) {
  5883.         return;
  5884.     }
  5885.  
  5886.     // prevent dupe events caused by frame re-runs
  5887.     if ( !gameLocal.isNewFrame ) {
  5888.         return;
  5889.     }
  5890.  
  5891.     outMsg.Init( msgBuf, sizeof( msgBuf ) );
  5892.     outMsg.BeginWriting();
  5893.     outMsg.WriteByte( GAME_RELIABLE_MESSAGE_EVENT );
  5894.     outMsg.WriteBits( gameLocal.GetSpawnId( this ), 32 );
  5895.     outMsg.WriteByte( eventId );
  5896.     outMsg.WriteLong( gameLocal.time );
  5897.     if ( msg ) {
  5898.         outMsg.WriteBits( msg->GetSize(), idMath::BitsForInteger( MAX_EVENT_PARAM_SIZE ) );
  5899.         outMsg.WriteData( msg->GetData(), msg->GetSize() );
  5900.     } else {
  5901.         outMsg.WriteBits( 0, idMath::BitsForInteger( MAX_EVENT_PARAM_SIZE ) );
  5902.     }
  5903.  
  5904.     networkSystem->ClientSendReliableMessage( outMsg );
  5905. }
  5906.  
  5907. /*
  5908. ================
  5909. idEntity::ServerReceiveEvent
  5910. ================
  5911. */
  5912. bool idEntity::ServerReceiveEvent( int event, int time, const idBitMsg &msg ) {
  5913.     switch( event ) {
  5914.         case 0: {
  5915.         }
  5916.         default: {
  5917.             return false;
  5918.         }
  5919.     }
  5920. }
  5921.  
  5922. /*
  5923. ================
  5924. idEntity::ClientReceiveEvent
  5925. ================
  5926. */
  5927. bool idEntity::ClientReceiveEvent( int event, int time, const idBitMsg &msg ) {
  5928.     const idSoundShader    *shader;
  5929.     s_channelType        channel;
  5930.  
  5931.     switch( event ) {
  5932.         case EVENT_STARTSOUNDSHADER: {
  5933.             // the sound stuff would early out
  5934.             assert( gameLocal.isNewFrame );
  5935.             if ( time < gameLocal.realClientTime - 300 ) {
  5936.                 // too old, skip it
  5937.                 common->DPrintf( "ent 0x%x: start sound shader too old (%d ms)\n", entityNumber, gameLocal.realClientTime - time );
  5938.                 return true;
  5939.             }
  5940.             shader = static_cast< const idSoundShader* >( idGameLocal::ReadDecl( msg, DECL_SOUND ) );
  5941.             channel = (s_channelType)msg.ReadByte();
  5942.             StartSoundShader( shader, channel, 0, false, NULL );
  5943.             return true;
  5944.         }
  5945.         case EVENT_STOPSOUNDSHADER: {
  5946.             // the sound stuff would early out
  5947.             assert( gameLocal.isNewFrame );
  5948.             channel = (s_channelType)msg.ReadByte();
  5949.             StopSound( channel, false );
  5950.             return true;
  5951.         }
  5952. // RAVEN BEGIN
  5953. // bdube: new events
  5954.         case EVENT_PLAYEFFECT_JOINT: {
  5955.             const idDecl*        effect;
  5956.             idCQuat                quat;
  5957.             idVec3                origin;
  5958.             rvClientEffect*        clientEffect;
  5959.             effectCategory_t    category;
  5960.             jointHandle_t        jointHandle;
  5961.             bool                loop;
  5962.  
  5963.             // TMP - not quite sure this is still used for anything
  5964.             common->Warning( "FIXME: idEntity::PlayEffect happens" );
  5965.             assert( false );
  5966.         
  5967.             effect = idGameLocal::ReadDecl( msg, DECL_EFFECT );
  5968.             jointHandle = ( jointHandle_t )msg.ReadLong();
  5969.             loop = ( msg.ReadBits ( 1 ) != 0 );
  5970.             origin.x = msg.ReadFloat( );
  5971.             origin.y = msg.ReadFloat( );
  5972.             origin.z = msg.ReadFloat( );
  5973.             category = ( effectCategory_t )msg.ReadByte();
  5974.  
  5975.             if ( bse->CanPlayRateLimited( category ) ) {
  5976.             // mwhitlock: Dynamic memory consolidation
  5977.                 RV_PUSH_SYS_HEAP_ID(RV_HEAP_ID_MULTIPLE_FRAME);
  5978.                 clientEffect = new rvClientEffect( effect );
  5979.                 RV_POP_HEAP();
  5980.  
  5981.                 clientEffect->SetOrigin ( vec3_origin );
  5982.                 clientEffect->SetAxis ( mat3_identity );
  5983.                 clientEffect->Bind( this, jointHandle );
  5984.  
  5985.                 clientEffect->Play( time, loop, origin );
  5986.             }
  5987.             return true;
  5988.         }
  5989.         
  5990.         case EVENT_PLAYEFFECT: {
  5991.             const idDecl*        effect;
  5992.             idCQuat                quat;
  5993.             idVec3                origin, origin2;
  5994.             rvClientEffect*        clientEffect;
  5995.             effectCategory_t    category;
  5996.             bool                loop;
  5997.             
  5998.             effect = idGameLocal::ReadDecl( msg, DECL_EFFECT );
  5999.  
  6000.             origin.x = msg.ReadFloat( );
  6001.             origin.y = msg.ReadFloat( );
  6002.             origin.z = msg.ReadFloat( );
  6003.             
  6004.             quat.x = msg.ReadFloat( );
  6005.             quat.y = msg.ReadFloat( );
  6006.             quat.z = msg.ReadFloat( );
  6007.  
  6008.             loop = ( msg.ReadBits( 1 ) != 0 );
  6009.  
  6010.             origin2.x = msg.ReadFloat( );
  6011.             origin2.y = msg.ReadFloat( );
  6012.             origin2.z = msg.ReadFloat( );
  6013.             category = ( effectCategory_t )msg.ReadByte();
  6014.  
  6015.             if ( bse->CanPlayRateLimited( category ) ) {
  6016.                 // mwhitlock: Dynamic memory consolidation
  6017.                 RV_PUSH_SYS_HEAP_ID(RV_HEAP_ID_MULTIPLE_FRAME);
  6018.                 clientEffect = new rvClientEffect( effect );
  6019.                 RV_POP_HEAP();
  6020.  
  6021.                 clientEffect->SetOrigin ( origin );
  6022.                 clientEffect->SetAxis ( quat.ToMat3() );
  6023.                 clientEffect->Bind ( this );
  6024.  
  6025.                 clientEffect->Play ( time, loop, origin2 );
  6026.             }
  6027.             return true;
  6028.         }
  6029. // RAVEN END        
  6030.         default: {
  6031.             return false;
  6032.         }
  6033.     }
  6034. //unreachable
  6035. //    return false;
  6036. }
  6037.  
  6038. // RAVEN BEGIN
  6039. // bdube: added
  6040. /*
  6041. ================
  6042. idEntity::ClientStale
  6043. ================
  6044. */
  6045. bool idEntity::ClientStale( void ) {
  6046.     FreeModelDef();
  6047.     UpdateVisuals();
  6048.     GetPhysics()->UnlinkClip();
  6049.     return false;
  6050. }
  6051.  
  6052. /*
  6053. ================
  6054. idEntity::ClientUnstale
  6055. ================
  6056. */
  6057. void idEntity::ClientUnstale( void ) {
  6058. }
  6059.  
  6060. /*
  6061. ================
  6062. idEntity::GetDamageEntity
  6063.  
  6064. Returns the entity that should take damage in place of this entity.  The default is the
  6065. entity itself.
  6066. ================
  6067. */
  6068. idEntity* idEntity::GetDamageEntity( void ) { 
  6069.     return forwardDamageEnt.IsValid() ? forwardDamageEnt.GetEntity() : this;
  6070. }
  6071.  
  6072. // rjohnson: moved entity info out of idGameLocal into its own function
  6073. /*
  6074. ================
  6075. idEntity::DrawDebugEntityInfo
  6076. ================
  6077. */
  6078. void idEntity::DrawDebugEntityInfo( idBounds *viewBounds, idBounds *viewTextBounds, idVec4 *overrideColor ) {
  6079.     idPlayer *player = gameLocal.GetLocalPlayer();
  6080.     if ( !player ) {
  6081.         return;
  6082.     }
  6083.  
  6084.     idMat3 axis = player->viewAngles.ToMat3();
  6085.     idVec3 up = axis[ 2 ] * 5.0f;
  6086.  
  6087.     // skip if the entity is very far away
  6088.     if ( viewBounds && !viewBounds->IntersectsBounds( GetPhysics()->GetAbsBounds() ) ) {
  6089.         return;
  6090.     }
  6091.  
  6092.     const idBounds &entBounds = GetPhysics()->GetAbsBounds();
  6093.  
  6094.     if (overrideColor) {
  6095.         if ( !entBounds.GetVolume() ) {
  6096.             gameRenderWorld->DebugBounds( *overrideColor, entBounds.Expand( 8.0f ), vec3_origin );
  6097.         } else {
  6098.             gameRenderWorld->DebugBounds( *overrideColor, entBounds, vec3_origin );
  6099.         }
  6100.     } else {
  6101.         int contents = GetPhysics()->GetContents();
  6102.         if ( contents & CONTENTS_BODY ) {
  6103.             gameRenderWorld->DebugBounds ( colorCyan, entBounds, vec3_origin );
  6104.         } else if ( contents & CONTENTS_TRIGGER ) {
  6105.             gameRenderWorld->DebugBounds( colorOrange, entBounds, vec3_origin );
  6106.         } else if ( contents & CONTENTS_SOLID ) {
  6107.             gameRenderWorld->DebugBounds( colorGreen, entBounds, vec3_origin );
  6108.         } else {
  6109.             if ( !entBounds.GetVolume() ) {
  6110.                 gameRenderWorld->DebugBounds( colorMdGrey, entBounds.Expand( 8.0f ), vec3_origin );
  6111.             } else {
  6112.                 gameRenderWorld->DebugBounds( colorMdGrey, entBounds, vec3_origin );
  6113.             }
  6114.         }
  6115.     }
  6116.  
  6117.     if ( !viewTextBounds || viewTextBounds->IntersectsBounds( entBounds ) ) {
  6118.         gameRenderWorld->DrawText( name.c_str(), entBounds.GetCenter(), 0.1f, colorWhite, axis, 1 );
  6119.         gameRenderWorld->DrawText( va( "#%d", entityNumber ), entBounds.GetCenter() + up, 0.1f, colorWhite, axis, 1 );
  6120.  
  6121.         if ( gameLocal.GetLocalPlayer() && this != gameLocal.GetLocalPlayer() && teamMaster != gameLocal.GetLocalPlayer() ) {
  6122.             gameRenderWorld->DebugLine ( colorRed, GetPhysics()->GetCenterMass(), GetPhysics()->GetCenterMass() + 50.0f * GetPhysics()->GetAxis()[0] );
  6123.             gameRenderWorld->DebugLine ( colorGreen, GetPhysics()->GetCenterMass(), GetPhysics()->GetCenterMass() + 50.0f * GetPhysics()->GetAxis()[1] );
  6124.             gameRenderWorld->DebugLine ( colorBlue, GetPhysics()->GetCenterMass(), GetPhysics()->GetCenterMass() + 50.0f * GetPhysics()->GetAxis()[2] );
  6125.         }
  6126.     }
  6127. }
  6128.  
  6129. /*
  6130. =====================
  6131. idEntity::SetInstance
  6132. =====================
  6133. */
  6134. void idEntity::SetInstance( int newInstance ) {
  6135.     instance = newInstance;
  6136.  
  6137.     if( gameLocal.isServer ) {
  6138.         SetClipWorld( newInstance );
  6139.     }
  6140. }
  6141.  
  6142. /*
  6143. =====================
  6144. idEntity::InstanceJoin
  6145. Gets called when the local player joins the same instance as this entity
  6146. =====================
  6147. */
  6148. void idEntity::InstanceJoin( void ) {
  6149.     assert( gameLocal.GetLocalPlayer() && gameLocal.GetLocalPlayer()->GetInstance() == instance );
  6150.  
  6151.     BecomeActive( TH_UPDATEVISUALS );
  6152.     Present();
  6153. }
  6154.  
  6155. /*
  6156. =====================
  6157. idEntity::InstanceLeave
  6158. Gets called when the local player leaves the same instance as this entity
  6159. =====================
  6160. */
  6161. void idEntity::InstanceLeave( void ) {
  6162.     assert( gameLocal.GetLocalPlayer() && gameLocal.GetLocalPlayer()->GetInstance() != instance );
  6163.  
  6164.     FreeLightDef();
  6165.     FreeModelDef();
  6166.     //RemoveClientEntities();
  6167.     BecomeInactive( TH_UPDATEVISUALS );
  6168. }
  6169.  
  6170. /*
  6171. =====================
  6172. idEntity::GetDebugInfo
  6173. =====================
  6174. */
  6175. void idEntity::GetDebugInfo ( debugInfoProc_t proc, void* userData ) {
  6176.     // Base class first
  6177.     idClass::GetDebugInfo ( proc, userData );
  6178.  
  6179.     proc ( "idEntity", "health",        va("%d",health), userData );
  6180.     proc ( "idEntity", "name",            name, userData );
  6181.     proc ( "idEntity", "entityNumber",  va("%d",entityNumber), userData );
  6182.     proc ( "idEntity", "origin",        renderEntity.origin.ToString ( ), userData );
  6183.  
  6184.     proc ( "idEntity", "notarget",        fl.notarget?"true":"false", userData );
  6185.     proc ( "idEntity", "takedamage",    fl.takedamage?"true":"false", userData );
  6186.     proc ( "idEntity", "hidden",        fl.hidden?"true":"false", userData );
  6187.     proc ( "idEntity", "bindOrientated",fl.bindOrientated?"true":"false", userData );
  6188.     proc ( "idEntity", "isDormant",        fl.isDormant?"true":"false", userData );
  6189.     proc ( "idEntity", "neverDormant",    fl.neverDormant?"true":"false", userData );
  6190.     proc ( "idEntity", "isAIObstacle",    fl.isAIObstacle?"true":"false", userData );
  6191.  
  6192.     proc ( "idEntity", "forwardDamageEnt",forwardDamageEnt.GetEntity() ? forwardDamageEnt.GetEntity()->GetName() : "<none>", userData );
  6193.  
  6194.     proc ( "idEntity", "bindMaster",    bindMaster ? bindMaster->GetName() : "<none>", userData );
  6195.     proc ( "idEntity", "bindJoint",        va("%d",((int)bindJoint)), userData );
  6196.     proc ( "idEntity", "bindBody",        va("%d",bindBody), userData );
  6197.  
  6198.     proc ( "idEntity", "teamMaster",    teamMaster ? teamMaster->GetName() : "<none>", userData );
  6199.     proc ( "idEntity", "teamChain",        teamChain ? teamChain->GetName() : "<none>", userData );
  6200. }
  6201.  
  6202. // mwhitlock: memory profiling
  6203. /*
  6204. =====================
  6205. idEntity::Size()
  6206.  
  6207. Returns memory size of an idEntity instance
  6208. =====================
  6209. */
  6210.  
  6211. size_t idEntity::Size( void ) const
  6212. {
  6213.     // TODO: more crap needs to go here!
  6214.     return sizeof (idEntity);
  6215. }
  6216. // RAVEN END
  6217.  
  6218.  
  6219.  
  6220. /*
  6221. ===============================================================================
  6222.  
  6223.   idAnimatedEntity
  6224.  
  6225. ===============================================================================
  6226. */
  6227.  
  6228. const idEventDef EV_GetJointHandle( "getJointHandle", "s", 'd' );
  6229. const idEventDef EV_ClearAllJoints( "clearAllJoints" );
  6230. const idEventDef EV_ClearJoint( "clearJoint", "d" );
  6231. const idEventDef EV_SetJointPos( "setJointPos", "ddv" );
  6232. const idEventDef EV_SetJointAngle( "setJointAngle", "ddv" );
  6233. const idEventDef EV_GetJointPos( "getJointPos", "d", 'v' );
  6234. const idEventDef EV_GetJointAngle( "getJointAngle", "d", 'v' );
  6235.  
  6236.  
  6237. // RAVEN BEGIN
  6238. // bdube: programmer controlled joint events
  6239. const idEventDef EV_SetJointAngularVelocity ( "setJointAngularVelocity", "sfffd" );
  6240. const idEventDef EV_CollapseJoints ( "collapseJoints", "ss" );
  6241. // jshepard: clear out all animations still running on the model
  6242. const idEventDef EV_ClearAnims( "clearAnims" );
  6243.  
  6244. // RAVEN END
  6245.  
  6246. CLASS_DECLARATION( idEntity, idAnimatedEntity )
  6247.     EVENT( EV_GetJointHandle,        idAnimatedEntity::Event_GetJointHandle )
  6248.     EVENT( EV_ClearAllJoints,        idAnimatedEntity::Event_ClearAllJoints )
  6249.     EVENT( EV_ClearJoint,            idAnimatedEntity::Event_ClearJoint )
  6250.     EVENT( EV_SetJointPos,            idAnimatedEntity::Event_SetJointPos )
  6251.     EVENT( EV_SetJointAngle,        idAnimatedEntity::Event_SetJointAngle )
  6252.     EVENT( EV_GetJointPos,            idAnimatedEntity::Event_GetJointPos )
  6253.     EVENT( EV_GetJointAngle,        idAnimatedEntity::Event_GetJointAngle )
  6254.  
  6255. // RAVEEN BEGIN
  6256. // bdube: programmer controlled joint events
  6257.     EVENT( EV_SetJointAngularVelocity,    idAnimatedEntity::Event_SetJointAngularVelocity )
  6258.     EVENT( EV_CollapseJoints,            idAnimatedEntity::Event_CollapseJoints )
  6259. // RAVEN END
  6260. END_CLASS
  6261.  
  6262. /*
  6263. ================
  6264. idAnimatedEntity::idAnimatedEntity
  6265. ================
  6266. */
  6267. idAnimatedEntity::idAnimatedEntity() {
  6268.     animator.SetEntity( this );
  6269.     damageEffects = NULL;
  6270. }
  6271.  
  6272. /*
  6273. ================
  6274. idAnimatedEntity::~idAnimatedEntity
  6275. ================
  6276. */
  6277. idAnimatedEntity::~idAnimatedEntity() {
  6278.     damageEffect_t    *de;
  6279.  
  6280.     for ( de = damageEffects; de; de = damageEffects ) {
  6281.         damageEffects = de->next;
  6282.         delete de;
  6283.     }
  6284. }
  6285.  
  6286. /*
  6287. ================
  6288. idAnimatedEntity::Save
  6289.  
  6290. archives object for save game file
  6291. ================
  6292. */
  6293. void idAnimatedEntity::Save( idSaveGame *savefile ) const {
  6294.     animator.Save( savefile );
  6295.  
  6296.     // Wounds are very temporary, ignored at this time
  6297.     //damageEffect_t            *damageEffects;
  6298. }
  6299.  
  6300. /*
  6301. ================
  6302. idAnimatedEntity::Restore
  6303.  
  6304. unarchives object from save game file
  6305. ================
  6306. */
  6307. void idAnimatedEntity::Restore( idRestoreGame *savefile ) {
  6308.     animator.Restore( savefile );
  6309.  
  6310.     // check if the entity has an MD5 model
  6311.     if ( animator.ModelHandle() ) {
  6312.         // set the callback to update the joints
  6313.         renderEntity.callback = idEntity::ModelCallback;
  6314.         animator.GetJoints( &renderEntity.numJoints, &renderEntity.joints );
  6315.         animator.GetBounds( gameLocal.time, renderEntity.bounds );
  6316.         if ( modelDefHandle != -1 ) {
  6317.             gameRenderWorld->UpdateEntityDef( modelDefHandle, &renderEntity );
  6318.         }
  6319.     }
  6320. }
  6321.  
  6322. /*
  6323. ================
  6324. idAnimatedEntity::ClientPredictionThink
  6325. ================
  6326. */
  6327. void idAnimatedEntity::ClientPredictionThink( void ) {
  6328.     RunPhysics();
  6329.     UpdateAnimation();
  6330.     Present();
  6331. }
  6332.  
  6333. /*
  6334. ================
  6335. idAnimatedEntity::Think
  6336. ================
  6337. */
  6338. void idAnimatedEntity::Think( void ) {
  6339.     RunPhysics();
  6340.     UpdateAnimation();
  6341.     Present();
  6342. }
  6343.  
  6344. /*
  6345. ================
  6346. idAnimatedEntity::UpdateAnimation
  6347. ================
  6348. */
  6349. void idAnimatedEntity::UpdateAnimation( void ) {
  6350.     // don't do animations if they're not enabled
  6351.     if ( !( thinkFlags & TH_ANIMATE ) ) {
  6352.         return;
  6353.     }
  6354.  
  6355.     // is the model an MD5?
  6356.     if ( !animator.ModelHandle() ) {
  6357.         // no, so nothing to do
  6358.         return;
  6359.     }
  6360.  
  6361. // RAVEN BEGIN
  6362. // bgeisler: for triggered anims
  6363.     // call any frame commands that have happened in the past frame
  6364.     if ( !fl.hidden || fl.triggerAnim )  {
  6365.         animator.ServiceAnims( gameLocal.previousTime, gameLocal.time );
  6366.     }
  6367. // RAVEN END
  6368.  
  6369.     // if the model is animating then we have to update it
  6370.     if ( !animator.FrameHasChanged( gameLocal.time ) ) {
  6371.         // still fine the way it was
  6372.         return;
  6373.     }
  6374.  
  6375.     // get the latest frame bounds
  6376.     animator.GetBounds( gameLocal.time, renderEntity.bounds );
  6377.     if ( renderEntity.bounds.IsCleared() && !fl.hidden ) {
  6378.         gameLocal.DPrintf( "%d: inside out bounds\n", gameLocal.time );
  6379.     }
  6380.  
  6381.     // update the renderEntity
  6382.     UpdateVisuals();
  6383.  
  6384.     // the animation is updated
  6385.     animator.ClearForceUpdate();
  6386. }
  6387.  
  6388. /*
  6389. ================
  6390. idAnimatedEntity::GetAnimator
  6391. ================
  6392. */
  6393. idAnimator *idAnimatedEntity::GetAnimator( void ) {
  6394.     return &animator;
  6395. }
  6396.  
  6397. /*
  6398. ================
  6399. idAnimatedEntity::SetModel
  6400. ================
  6401. */
  6402. void idAnimatedEntity::SetModel( const char *modelname ) {
  6403.     FreeModelDef();
  6404.  
  6405.     renderEntity.hModel = animator.SetModel( modelname );
  6406.     if ( !renderEntity.hModel ) {
  6407.         idEntity::SetModel( modelname );
  6408.         return;
  6409.     }
  6410.  
  6411.     if ( !renderEntity.customSkin ) {
  6412.         renderEntity.customSkin = animator.ModelDef()->GetDefaultSkin();
  6413.     }
  6414.  
  6415.     // set the callback to update the joints
  6416.     renderEntity.callback = idEntity::ModelCallback;
  6417.     animator.GetJoints( &renderEntity.numJoints, &renderEntity.joints );
  6418.     animator.GetBounds( gameLocal.time, renderEntity.bounds );
  6419.  
  6420.     UpdateVisuals();
  6421. }
  6422.  
  6423. /*
  6424. =====================
  6425. idAnimatedEntity::GetJointWorldTransform
  6426. =====================
  6427. */
  6428. bool idAnimatedEntity::GetJointWorldTransform( jointHandle_t jointHandle, int currentTime, idVec3 &offset, idMat3 &axis ) {
  6429.     if ( g_perfTest_noJointTransform.GetBool() ) {
  6430.         offset = GetPhysics()->GetCenterMass();
  6431.         axis = renderEntity.axis;
  6432.         return true;
  6433.     }
  6434.  
  6435.     if ( !animator.GetJointTransform( jointHandle, currentTime, offset, axis ) ) {
  6436.         return false;
  6437.     }
  6438.  
  6439.     ConvertLocalToWorldTransform( offset, axis );
  6440.     return true;
  6441. }
  6442.  
  6443. /*
  6444. ==============
  6445. idAnimatedEntity::GetJointTransformForAnim
  6446. ==============
  6447. */
  6448. bool idAnimatedEntity::GetJointTransformForAnim( jointHandle_t jointHandle, int animNum, int frameTime, idVec3 &offset, idMat3 &axis ) const {
  6449.     const idAnim    *anim;
  6450.     int                numJoints;
  6451.     idJointMat        *frame;
  6452.  
  6453.     if ( g_perfTest_noJointTransform.GetBool() ) {
  6454.         offset = GetPhysics()->GetCenterMass() - GetPhysics()->GetOrigin();
  6455.         axis = renderEntity.axis;
  6456.         return true;
  6457.     }
  6458.  
  6459.     anim = animator.GetAnim( animNum );
  6460.     if ( !anim ) {
  6461.         assert( 0 );
  6462.         return false;
  6463.     }
  6464.  
  6465.     numJoints = animator.NumJoints();
  6466.     if ( ( jointHandle < 0 ) || ( jointHandle >= numJoints ) ) {
  6467.         assert( 0 );
  6468.         return false;
  6469.     }
  6470.  
  6471.     frame = ( idJointMat * )_alloca16( numJoints * sizeof( idJointMat ) );
  6472.     gameEdit->ANIM_CreateAnimFrame( animator.ModelHandle(), anim->MD5Anim( 0 ), renderEntity.numJoints, frame, frameTime, animator.ModelDef()->GetVisualOffset(), animator.RemoveOrigin() );
  6473.  
  6474.     offset = frame[ jointHandle ].ToVec3();
  6475.     axis = frame[ jointHandle ].ToMat3();
  6476.     
  6477.     return true;
  6478. }
  6479.  
  6480. // RAVEN BEGIN
  6481. // ddynerman: removed/merged AddLocalDamageEffect() (redundant math)
  6482. /*
  6483. ==============
  6484. idAnimatedEntity::AddDamageEffect
  6485.  
  6486.   Dammage effects track the animating impact position, spitting out particles.
  6487. ==============
  6488. */
  6489. void idAnimatedEntity::AddDamageEffect( const trace_t &collision, const idVec3 &velocity, const char *damageDefName, idEntity* inflictor ) {
  6490.     // ddynerman: note, on client the collision struct is incomplete.  Only contains impact point and material
  6491.     const char *splat, *decal, *key;
  6492.     idVec3 dir;
  6493.  
  6494. // RAVEN BEGIN
  6495. // mekberg: changed from g_bloodEffects to g_decals
  6496.     if ( !g_decals.GetBool() ) {
  6497.         return;
  6498.     }
  6499. // RAVEN END
  6500.  
  6501.     const idDeclEntityDef *def = gameLocal.FindEntityDef( damageDefName, false );
  6502.     if ( def == NULL || !def->dict.GetBool ( "bleed" ) ) {
  6503.         return;
  6504.     }
  6505.  
  6506.     if ( !spawnArgs.GetBool( "bleed" ) ) {
  6507.         return;
  6508.     }
  6509.  
  6510.     dir = velocity;
  6511.     dir.Normalize();
  6512.  
  6513.     if ( gameLocal.isServer ) {
  6514.         idBitMsg    msg;
  6515.         byte        msgBuf[MAX_EVENT_PARAM_SIZE];
  6516.  
  6517.         msg.Init( msgBuf, sizeof( msgBuf ) );
  6518.         msg.BeginWriting();
  6519.         msg.WriteFloat( collision.c.point[0] );
  6520.         msg.WriteFloat( collision.c.point[1] );
  6521.         msg.WriteFloat( collision.c.point[2] );
  6522.         msg.WriteDir( dir, 24 );
  6523.         idGameLocal::WriteDecl( msg, def );
  6524.         idGameLocal::WriteDecl( msg, collision.c.material );
  6525.         ServerSendInstanceEvent( EVENT_ADD_DAMAGE_EFFECT, &msg, false, -1 );
  6526.     }
  6527.  
  6528.     if ( gameLocal.GetLocalPlayer() && GetInstance() != gameLocal.GetLocalPlayer()->GetInstance() ) {
  6529.         return; // no blood from other instances
  6530.     }
  6531.  
  6532.     // blood splats are thrown onto nearby surfaces
  6533.     splat = NULL;
  6534.     if ( collision.c.material->GetMaterialType() ) {
  6535.         key = va( "mtr_splat_%s", collision.c.material->GetMaterialType()->GetName() );
  6536.         splat = spawnArgs.RandomPrefix( key, gameLocal.random );
  6537.     }
  6538.     if ( !splat || !*splat ) {
  6539.         splat = spawnArgs.RandomPrefix( "mtr_splat", gameLocal.random );
  6540.     }
  6541.     if ( splat && *splat ) {
  6542.         //jshepard original 64.0f
  6543.         // dluetscher: changed from 64. to 48. for performance reasons
  6544.         gameLocal.BloodSplat( this, collision.c.point, dir, 48.0f, splat );
  6545.     }
  6546.  
  6547.     // can't see wounds on the player model in single player mode
  6548.     if ( !( IsType( idPlayer::GetClassType() ) && !gameLocal.isMultiplayer ) ) {
  6549.         //If this is a buddy marine, no wound decals until they're actually dead unless it's mp.
  6550.         if ( gameLocal.isMultiplayer 
  6551.             || !IsType( idAI::GetClassType() ) 
  6552.             || this->health <= 0
  6553.             || ((idAI*)this)->team != AITEAM_MARINE ) {
  6554.             // place a wound overlay on the model
  6555.             decal = NULL;
  6556.             if ( collision.c.material->GetMaterialType() ) {
  6557.                 key = va( "mtr_wound_%s", collision.c.material->GetMaterialType()->GetName() );
  6558.                 decal = spawnArgs.RandomPrefix( key, gameLocal.random );
  6559.             }
  6560.             if ( !decal || !*decal ) {
  6561.                 decal = spawnArgs.RandomPrefix( "mtr_wound", gameLocal.random );
  6562.             }
  6563.             if ( decal && *decal ) {
  6564.                 ProjectOverlay( collision.c.point, dir, 20.0f, decal );
  6565.             }
  6566.         }
  6567.     }
  6568. }
  6569. // RAVEN END
  6570.  
  6571. /*
  6572. ==============
  6573. idAnimatedEntity::GetDefaultSurfaceType
  6574. ==============
  6575. */
  6576. int    idAnimatedEntity::GetDefaultSurfaceType( void ) const {
  6577.     return SURFTYPE_METAL;
  6578. }
  6579.  
  6580. /*
  6581. ================
  6582. idAnimatedEntity::ClientReceiveEvent
  6583. ================
  6584. */
  6585. bool idAnimatedEntity::ClientReceiveEvent( int event, int time, const idBitMsg &msg ) {
  6586.     idVec3 origin, dir;
  6587.  
  6588.     switch( event ) {
  6589.         case EVENT_ADD_DAMAGE_EFFECT: {
  6590.             origin[0] = msg.ReadFloat();
  6591.             origin[1] = msg.ReadFloat();
  6592.             origin[2] = msg.ReadFloat();
  6593.             dir = msg.ReadDir( 24 );
  6594.             const idDeclEntityDef *damageDef = static_cast< const idDeclEntityDef* >( idGameLocal::ReadDecl( msg, DECL_ENTITYDEF ) );
  6595.             const idMaterial *collisionMaterial = static_cast< const idMaterial* >( idGameLocal::ReadDecl( msg, DECL_MATERIAL ) );
  6596. // RAVEN BEGIN
  6597. // ddynerman: removed redundant AddLocalDamageEffect()
  6598.             trace_t collision;
  6599.             collision.c.point = origin;
  6600.             collision.c.material = collisionMaterial;
  6601.             AddDamageEffect( collision, dir, damageDef->GetName(), NULL );
  6602. // RAVEN END
  6603.             return true;
  6604.         }
  6605.         default: {
  6606.             return idEntity::ClientReceiveEvent( event, time, msg );
  6607.         }
  6608.     }
  6609. //unreachable
  6610. //    return false;
  6611. }
  6612.  
  6613. // RAVEN BEGIN
  6614. // abahr: so we don't crash if UpdateModel is called from a destructor
  6615. /*
  6616. ================
  6617. idAnimatedEntity::UpdateRenderEntityCallback
  6618. ================
  6619. */
  6620. void idAnimatedEntity::UpdateRenderEntityCallback() {
  6621.     // check if the entity has an MD5 model
  6622.     idAnimator *animator = GetAnimator();
  6623.     if ( animator && animator->ModelHandle() ) {
  6624.         // set the callback to update the joints
  6625.         renderEntity.callback = idEntity::ModelCallback;
  6626.     }
  6627. }
  6628. // RAVEN END
  6629.  
  6630. /*
  6631. ================
  6632. idAnimatedEntity::Event_GetJointHandle
  6633.  
  6634. looks up the number of the specified joint.  returns INVALID_JOINT if the joint is not found.
  6635. ================
  6636. */
  6637. void idAnimatedEntity::Event_GetJointHandle( const char *jointname ) {
  6638.     jointHandle_t joint;
  6639.  
  6640.     joint = animator.GetJointHandle( jointname );
  6641.     idThread::ReturnInt( joint );
  6642. }
  6643.  
  6644. /*
  6645. ================
  6646. idAnimatedEntity::Event_ClearAllJoints
  6647.  
  6648. removes any custom transforms on all joints
  6649. ================
  6650. */
  6651. void idAnimatedEntity::Event_ClearAllJoints( void ) {
  6652.     animator.ClearAllJoints();
  6653. }
  6654.  
  6655. /*
  6656. ================
  6657. idAnimatedEntity::Event_ClearJoint
  6658.  
  6659. removes any custom transforms on the specified joint
  6660. ================
  6661. */
  6662. void idAnimatedEntity::Event_ClearJoint( jointHandle_t jointnum ) {
  6663.     animator.ClearJoint( jointnum );
  6664. }
  6665.  
  6666. /*
  6667. ================
  6668. idAnimatedEntity::Event_ClearAnims
  6669.  
  6670. Clears any animation running on the animated entity
  6671. ================
  6672. */
  6673. void idAnimatedEntity::Event_ClearAnims( void ) {
  6674.     animator.Clear( ANIMCHANNEL_ALL, gameLocal.GetTime(), gameLocal.GetTime() ); 
  6675. }
  6676.  
  6677. /*
  6678. ================
  6679. idAnimatedEntity::Event_SetJointPos
  6680.  
  6681. modifies the position of the joint based on the transform type
  6682. ================
  6683. */
  6684. void idAnimatedEntity::Event_SetJointPos( jointHandle_t jointnum, jointModTransform_t transform_type, const idVec3 &pos ) {
  6685.     animator.SetJointPos( jointnum, transform_type, pos );
  6686. }
  6687.  
  6688. /*
  6689. ================
  6690. idAnimatedEntity::Event_SetJointAngle
  6691.  
  6692. modifies the orientation of the joint based on the transform type
  6693. ================
  6694. */
  6695. void idAnimatedEntity::Event_SetJointAngle( jointHandle_t jointnum, jointModTransform_t transform_type, const idAngles &angles ) {
  6696.     idMat3 mat;
  6697.  
  6698.     mat = angles.ToMat3();
  6699.     animator.SetJointAxis( jointnum, transform_type, mat );
  6700. }
  6701.  
  6702. /*
  6703. ================
  6704. idAnimatedEntity::Event_GetJointPos
  6705.  
  6706. returns the position of the joint in worldspace
  6707. ================
  6708. */
  6709. void idAnimatedEntity::Event_GetJointPos( jointHandle_t jointnum ) {
  6710.     idVec3 offset;
  6711.     idMat3 axis;
  6712.  
  6713.     if ( !GetJointWorldTransform( jointnum, gameLocal.time, offset, axis ) ) {
  6714.         gameLocal.Warning( "Joint # %d out of range on entity '%s'",  jointnum, name.c_str() );
  6715.     }
  6716.  
  6717.     idThread::ReturnVector( offset );
  6718. }
  6719.  
  6720. /*
  6721. ================
  6722. idAnimatedEntity::Event_GetJointAngle
  6723.  
  6724. returns the orientation of the joint in worldspace
  6725. ================
  6726. */
  6727. void idAnimatedEntity::Event_GetJointAngle( jointHandle_t jointnum ) {
  6728.     idVec3 offset;
  6729.     idMat3 axis;
  6730.  
  6731.     if ( !GetJointWorldTransform( jointnum, gameLocal.time, offset, axis ) ) {
  6732.         gameLocal.Warning( "Joint # %d out of range on entity '%s'",  jointnum, name.c_str() );
  6733.     }
  6734.  
  6735.     idAngles ang = axis.ToAngles();
  6736.     idVec3 vec( ang[ 0 ], ang[ 1 ], ang[ 2 ] );
  6737.     idThread::ReturnVector( vec );
  6738. }
  6739.  
  6740. // RAVEN BEGIN
  6741. // bdube: moved to idAnimatedEntity
  6742. /*
  6743. ================
  6744. idAnimatedEntity::Event_SetJointAngularVelocity
  6745. ================
  6746. */
  6747. void idAnimatedEntity::Event_SetJointAngularVelocity ( const char* jointName, float pitch, float yaw, float roll, int blendTime ) {
  6748.     jointHandle_t joint = animator.GetJointHandle ( jointName );
  6749.     if ( joint == INVALID_JOINT ) {
  6750.         return;
  6751.     }
  6752.     
  6753.     animator.SetJointAngularVelocity ( joint, idAngles(pitch,yaw,roll), gameLocal.time, blendTime );
  6754. }
  6755.  
  6756. /*
  6757. ================
  6758. idAnimatedEntity::Event_CollapseJoints
  6759. ================
  6760. */
  6761. void idAnimatedEntity::Event_CollapseJoints ( const char* jointnames, const char* collapseTo ) {
  6762.     jointHandle_t collapseToJoint = animator.GetJointHandle ( collapseTo );
  6763.     if ( collapseToJoint == INVALID_JOINT ) {
  6764.         return;
  6765.     }
  6766.  
  6767.     animator.CollapseJoints ( jointnames, collapseToJoint );    
  6768. }
  6769. // RAVEN END
  6770.  
  6771.