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

  1. //----------------------------------------------------------------
  2. // ClientMoveable.cpp
  3. //
  4. // Copyright 2002-2004 Raven Software
  5. //----------------------------------------------------------------
  6.  
  7. #include "../../idlib/precompiled.h"
  8. #pragma hdrstop
  9.  
  10. #include "../Game_local.h"
  11.  
  12. /*
  13. ===============================================================================
  14.  
  15. rvClientMoveable
  16.  
  17. ===============================================================================
  18. */
  19. const idEventDef CL_FadeOut( "<fadeOut>", "d" );
  20. const idEventDef CL_ClearDepthHack ( "<clearDepthHack>" );
  21.  
  22. static const float BOUNCE_SOUND_MIN_VELOCITY    = 100.0f;
  23. static const float BOUNCE_SOUND_MAX_VELOCITY    = 200.0f;
  24. static const int   BOUNCE_SOUND_DELAY            = 200;
  25.  
  26. CLASS_DECLARATION( rvClientEntity, rvClientMoveable )
  27.     EVENT( CL_FadeOut,            rvClientMoveable::Event_FadeOut )
  28.     EVENT( CL_ClearDepthHack,    rvClientMoveable::Event_ClearDepthHack )
  29. END_CLASS
  30.  
  31.  
  32. /*
  33. ================
  34. rvClientMoveable::rvClientMoveable
  35. ================
  36. */
  37. rvClientMoveable::rvClientMoveable ( void ) {
  38.     memset ( &renderEntity, 0, sizeof(renderEntity) );
  39.     entityDefHandle = -1;
  40.     scale.Init( 0, 0, 1.0f, 1.0f );
  41. }
  42.  
  43. /*
  44. ================
  45. rvClientMoveable::~rvClientMoveable
  46. ================
  47. */
  48. rvClientMoveable::~rvClientMoveable ( void ) {
  49.     FreeEntityDef ( );
  50.  
  51.     // Remove any trail effect if there is one
  52.     if ( trailEffect ) {
  53.         trailEffect->Stop ( );
  54.     }
  55. }
  56.  
  57. /*
  58. ================
  59. rvClientMoveable::FreeEntityDef
  60. ================
  61. */
  62. void rvClientMoveable::FreeEntityDef ( void ) {
  63.     if ( entityDefHandle >= 0 ) {
  64.         gameRenderWorld->FreeEntityDef ( entityDefHandle );
  65.         entityDefHandle = -1;
  66.     }    
  67. }
  68.  
  69. idVec3 simpleTri[3] =
  70. {
  71.     idVec3( -1.0, -1.0, 0.0 ),
  72.     idVec3( 0.0, 2.0, 0.0 ),
  73.     idVec3( 2.0, 0.0, 0.0 )
  74. };
  75.  
  76. /*
  77. ================
  78. rvClientMoveable::Spawn
  79. ================
  80. */
  81. void rvClientMoveable::Spawn ( const idDict* spawnArgs, idEntity* owner ) {
  82.     assert ( spawnArgs );
  83.  
  84.     // parse static models the same way the editor display does
  85.     gameEdit->ParseSpawnArgsToRenderEntity( spawnArgs, &renderEntity );
  86.  
  87.     idTraceModel    trm;
  88.     int                clipShrink;
  89.     idStr            clipModelName;
  90.  
  91.     // check if a clip model is set
  92.     spawnArgs->GetString( "clipmodel", "", clipModelName );
  93.     if ( !clipModelName.Length ()  ) {
  94.         clipModelName = spawnArgs->GetString ( "model" );        // use the visual model
  95.     }
  96.  
  97.     if ( clipModelName == SIMPLE_TRI_NAME ) {
  98.         trm.SetupPolygon( simpleTri, 3 );
  99.     } else {
  100.         clipModelName.BackSlashesToSlashes();
  101.  
  102.         if ( !collisionModelManager->TrmFromModel( gameLocal.GetMapName(), clipModelName, trm ) ) {
  103.             gameLocal.Error( "rvClientMoveable '%d': cannot load collision model %s", entityNumber, clipModelName.c_str() );
  104.             return;
  105.         }
  106.     }
  107.  
  108.     // if the model should be shrunk
  109.     clipShrink = spawnArgs->GetInt( "clipshrink" );
  110.     if ( clipShrink != 0 ) {
  111.         trm.Shrink( clipShrink * CM_CLIP_EPSILON );
  112.     }
  113.  
  114.     physicsObj.SetSelf ( gameLocal.entities[ENTITYNUM_CLIENT] );        
  115.     physicsObj.SetClipModel ( new idClipModel( trm ), spawnArgs->GetFloat ( "density", "0.5" ), entityNumber );
  116.     physicsObj.GetClipModel()->SetOwner( owner );
  117.     physicsObj.GetClipModel()->SetEntity( owner );
  118.     physicsObj.SetOrigin( GetOrigin() );
  119.     physicsObj.SetAxis( GetAxis() );
  120.     physicsObj.SetBouncyness( spawnArgs->GetFloat( "bouncyness", "0.6" ) );
  121.     physicsObj.SetFriction( spawnArgs->GetFloat("linear_friction", "0.6"), spawnArgs->GetFloat( "angular_friction", "0.6"), spawnArgs->GetFloat("friction", "0.05") );
  122.     physicsObj.SetGravity( gameLocal.GetCurrentGravity(this) );
  123.     physicsObj.SetContents( 0 );
  124.     // abahr: changed to MASK_SHOT_RENDERMODEL because brass was getting pinched between the player and the wall in some cases
  125.     //            may want to try something cheaper.
  126.     physicsObj.SetClipMask( CONTENTS_OPAQUE ); // MASK_SHOT_RENDERMODEL | CONTENTS_CORPSE | CONTENTS_MOVEABLECLIP | CONTENTS_WATER );
  127.     physicsObj.Activate ( );
  128.  
  129.     trailEffect = gameLocal.PlayEffect ( *spawnArgs, "fx_trail", physicsObj.GetCenterMass(), GetAxis(), true );    
  130.     trailAttenuateSpeed = spawnArgs->GetFloat ( "trailAttenuateSpeed", "200" );
  131.     
  132.     bounceSoundShader = declManager->FindSound ( spawnArgs->GetString ( "snd_bounce" ), false );
  133.     bounceSoundTime   = 0;
  134.     mPlayBounceSoundOnce = spawnArgs->GetBool("bounce_sound_once");
  135.     mHasBounced = false;
  136.     
  137.     scale.Init( gameLocal.GetTime(), SEC2MS(spawnArgs->GetFloat("scale_reset_duration", "0.2")), Max(VECTOR_EPSILON, spawnArgs->GetFloat("scale", "1.0f")), 1.0f );
  138. }
  139.  
  140. /*
  141. ================
  142. rvClientMoveable::Think
  143. ================
  144. */
  145. void rvClientMoveable::Think ( void ) {
  146.     if( bindMaster && (bindMaster->GetRenderEntity()->hModel && bindMaster->GetModelDefHandle() == -1) ) {
  147.         return;
  148.     }
  149.  
  150.     RunPhysics ( );    
  151.  
  152.     // Special case the sound update to use the center mass since the origin may be in an odd place
  153.     idSoundEmitter *emitter = soundSystem->EmitterForIndex( SOUNDWORLD_GAME, refSound.referenceSoundHandle );
  154.     if ( emitter ) {
  155.         refSound.origin = physicsObj.GetCenterMass ( );
  156.         refSound.velocity = physicsObj.GetLinearVelocity();
  157.         emitter->UpdateEmitter( refSound.origin, refSound.velocity, refSound.listenerId, &refSound.parms );
  158.     }
  159.  
  160.     // Keep the trail effect following
  161.     if ( trailEffect ) {
  162.         float speed;
  163.         speed = idMath::ClampFloat ( 0, trailAttenuateSpeed, physicsObj.GetLinearVelocity ( ).LengthFast ( ) );
  164.         if ( physicsObj.IsAtRest ( ) ) {
  165.             trailEffect->Stop ( );
  166.             trailEffect = NULL;
  167.         } else {
  168.             trailEffect->SetOrigin ( physicsObj.GetCenterMass() );
  169.             trailEffect->SetAxis ( worldAxis );
  170.             trailEffect->Attenuate ( speed / trailAttenuateSpeed );
  171.         }
  172.     }
  173.  
  174.     renderEntity.origin = worldOrigin;
  175.     renderEntity.axis = worldAxis * scale.GetCurrentValue( gameLocal.GetTime() );
  176.  
  177.     // add to refresh list
  178.     if ( entityDefHandle == -1 ) {
  179.         entityDefHandle = gameRenderWorld->AddEntityDef( &renderEntity );
  180.     } else {
  181.         gameRenderWorld->UpdateEntityDef( entityDefHandle, &renderEntity );
  182.     }        
  183. }
  184.  
  185. /*
  186. ================
  187. rvClientMoveable::GetPhysics
  188. ================
  189. */
  190. idPhysics* rvClientMoveable::GetPhysics ( void ) const {
  191.     return (idPhysics*)&physicsObj;
  192. }
  193.  
  194. /*
  195. ================
  196. rvClientMoveable::Collide
  197. ================
  198. */
  199. bool rvClientMoveable::Collide ( const trace_t &collision, const idVec3 &velocity ) {    
  200.     if (mPlayBounceSoundOnce && mHasBounced)
  201.     {
  202.         return false;
  203.     }
  204.     if ( bounceSoundShader && gameLocal.time > bounceSoundTime ) {
  205.         float speed;
  206.         speed = velocity.LengthFast ( );
  207.         if ( speed > BOUNCE_SOUND_MIN_VELOCITY ) {
  208.             StartSoundShader ( bounceSoundShader, SND_CHANNEL_BODY, 0 );
  209.             bounceSoundTime = BOUNCE_SOUND_DELAY;
  210.             mHasBounced = true;
  211.         }
  212.     }    
  213.         
  214.     return false;
  215. }
  216.  
  217. /*
  218. ================
  219. rvClientMoveable::Save
  220. ================
  221. */
  222. void rvClientMoveable::Save( idSaveGame *savefile ) const {
  223.     savefile->WriteRenderEntity( renderEntity );
  224.     savefile->WriteInt( entityDefHandle );
  225.  
  226.     trailEffect.Save( savefile );
  227.     savefile->WriteFloat( trailAttenuateSpeed );
  228.         
  229.     savefile->WriteStaticObject( physicsObj );
  230.     
  231.     savefile->WriteInt( bounceSoundTime );
  232.     savefile->WriteSoundShader( bounceSoundShader );
  233.  
  234.     savefile->WriteBool(mPlayBounceSoundOnce);
  235.     savefile->WriteBool(mHasBounced);
  236.  
  237.     // TOSAVE: idInterpolate<float>    scale;
  238. }
  239.  
  240. /*
  241. ================
  242. rvClientMoveable::Restore
  243. ================
  244. */
  245. void rvClientMoveable::Restore( idRestoreGame *savefile ) {
  246.     savefile->ReadRenderEntity( renderEntity, NULL );
  247.     savefile->ReadInt( entityDefHandle );
  248.  
  249.     trailEffect.Restore( savefile );
  250.     savefile->ReadFloat( trailAttenuateSpeed );
  251.         
  252.     savefile->ReadStaticObject( physicsObj );
  253.     
  254.     savefile->ReadInt( bounceSoundTime );
  255.     savefile->ReadSoundShader( bounceSoundShader );
  256.  
  257.     savefile->ReadBool(mPlayBounceSoundOnce);
  258.     savefile->ReadBool(mHasBounced);
  259.  
  260.     // restore must retrieve entityDefHandle from the renderer
  261.      if ( entityDefHandle != -1 ) {
  262.          entityDefHandle = gameRenderWorld->AddEntityDef( &renderEntity );
  263.      }
  264.  
  265.     // TORESTORE: idInterpolate<float>    scale;
  266. }
  267.  
  268. /*
  269. ================
  270. rvClientMoveable::Event_FadeOut
  271. ================
  272. */
  273. void rvClientMoveable::Event_FadeOut ( int duration ) {
  274.     renderEntity.noShadow = true;
  275.     renderEntity.shaderParms[ SHADERPARM_TIME_OF_DEATH ] = gameLocal.time * 0.001f;
  276.     PostEventMS ( &EV_Remove, duration );    
  277. }
  278.  
  279. /*
  280. ================
  281. rvClientMoveable::Event_ClearDepthHack
  282. ================
  283. */
  284. void rvClientMoveable::Event_ClearDepthHack ( void ) {
  285.     renderEntity.weaponDepthHackInViewID = 0;
  286. }
  287.  
  288. /*
  289. ================
  290. rvClientMoveable::SpawnClientMoveables
  291. ================
  292. */
  293. void rvClientMoveable::SpawnClientMoveables( idEntity* ent, const char *type, idList<rvClientMoveable *>* list ) {
  294.     const idKeyValue *kv;
  295.     idVec3 origin;
  296.     idMat3 axis;
  297.     
  298.     if( list == NULL || type == NULL ) {
  299.         return;
  300.     }
  301.  
  302.     // drop all items
  303.     kv = ent->spawnArgs.MatchPrefix( va( "def_%s", type ), NULL );
  304.     while ( kv ) {
  305.         origin = ent->GetPhysics()->GetOrigin();
  306.         axis = ent->GetPhysics()->GetAxis();
  307.  
  308. // RAVEN BEGIN
  309. // jnewquist: Use accessor for static class type 
  310.         if( ent->IsType( idAnimatedEntity::GetClassType() ) ) {
  311. // RAVEN END
  312.             idAnimatedEntity* animEnt = static_cast<idAnimatedEntity*>(ent);
  313.             jointHandle_t clientMoveableJoint;
  314.     
  315.             const char* clientMoveableJointName = ent->spawnArgs.GetString( va( "%s_joint", kv->GetKey().c_str() + 4 ) );
  316.         
  317.             // use a joint if specified
  318.             if ( idStr::Icmp( clientMoveableJointName, "") ) {
  319.                 clientMoveableJoint = animEnt->GetAnimator()->GetJointHandle( clientMoveableJointName );
  320.  
  321.                 if ( !animEnt->GetJointWorldTransform( clientMoveableJoint, gameLocal.time, origin, axis ) ) {
  322.                     gameLocal.Warning( "%s refers to invalid joint '%s' on entity '%s'\n", va( "%s_joint", kv->GetKey().c_str() + 4 ), clientMoveableJointName, ent->name.c_str() );
  323.                     origin = ent->GetPhysics()->GetOrigin();
  324.                     axis = ent->GetPhysics()->GetAxis();
  325.                 }
  326.             } 
  327.         } 
  328.  
  329.         // spawn the entity
  330.         const idDict* entityDef = gameLocal.FindEntityDefDict ( kv->GetValue().c_str(), false );
  331.     
  332.         if ( entityDef == NULL ) {
  333.             gameLocal.Warning( "%s refers to invalid entity def '%s' on entity '%s'\n", kv->GetKey().c_str(), kv->GetValue().c_str(), ent->name.c_str() );
  334.             break;
  335.         }
  336.     
  337. // RAVEN BEGIN
  338. // mwhitlock: Dynamic memory consolidation
  339.         RV_PUSH_HEAP_MEM(ent);
  340. // RAVEN END
  341.         rvClientMoveable *newModel = new rvClientMoveable();
  342. // RAVEN BEGIN
  343. // mwhitlock: Dynamic memory consolidation
  344.         RV_POP_HEAP();
  345. // RAVEN END
  346.         newModel->SetOrigin ( origin );
  347.         newModel->SetAxis( axis );
  348.         newModel->Spawn ( entityDef );    
  349.  
  350.         list->Append( newModel );
  351.         kv = ent->spawnArgs.MatchPrefix( va( "def_%s", type ), kv );
  352.     }
  353. }
  354.  
  355.