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

  1. #include "../idlib/precompiled.h"
  2. #pragma hdrstop
  3.  
  4. #include "Game_local.h"
  5. #include "ai/AI.h"
  6.  
  7. #define RECORD_STATE_TRACE_LEN        2048.0f
  8.  
  9. class rvGamePlayback
  10. {
  11. public:
  12.                             rvGamePlayback( void );
  13.                             ~rvGamePlayback( void );
  14.  
  15.             void            RecordData( const usercmd_t &cmd, idEntity *source );
  16. private:
  17.             int                mStartTime;
  18.             byte            mOldFlags;
  19.             idStr            mName;
  20.             idClipModel        *mClipModel;
  21.             rvDeclPlayback    *mPlayback;
  22. };
  23.  
  24. idCVar g_recordPlayback( "g_recordPlayback", "0", CVAR_GAME | CVAR_INTEGER | CVAR_NOCHEAT, "record the player movement in a playback" );
  25. idCVar g_playPlayback( "g_playPlayback", "0", CVAR_GAME | CVAR_INTEGER | CVAR_NOCHEAT, "plays the current playback in a camera path" );
  26.  
  27. rvGamePlayback        *gamePlayback = NULL;
  28. rvCameraPlayback    *playbackCamera = NULL;
  29.  
  30. rvGamePlayback::rvGamePlayback( void )
  31. {
  32.     idStr            newName;
  33.     const idVec3 trace_mins( -1.0f, -1.0f, -1.0f );
  34.     const idVec3 trace_maxs( 1.0f, 1.0f, 1.0f );
  35.     const idBounds trace_bounds( trace_mins, trace_maxs );
  36.     idTraceModel    traceModel( trace_bounds );
  37.         
  38.     mStartTime = gameLocal.time;
  39.     mOldFlags = 0;
  40.     mClipModel = new idClipModel( traceModel );
  41.  
  42.     if( !g_currentPlayback.GetInteger() )
  43.     {
  44.         newName = declManager->GetNewName( DECL_PLAYBACK, "playbacks/untitled" );
  45.         mPlayback = ( rvDeclPlayback * )declManager->CreateNewDecl( DECL_PLAYBACK, newName, newName + ".playback" );
  46.         mPlayback->ReplaceSourceFileText();
  47.         mPlayback->Invalidate();
  48.  
  49.         g_currentPlayback.SetInteger( mPlayback->Index() );
  50.     }
  51.     else
  52.     {
  53.         mPlayback = ( rvDeclPlayback * )declManager->PlaybackByIndex( g_currentPlayback.GetInteger() );
  54.     }
  55.  
  56.     declManager->StartPlaybackRecord( mPlayback );
  57.     common->Printf( "Starting playback record to %s type %d\n", mPlayback->GetName(), g_recordPlayback.GetInteger() );
  58. }
  59.  
  60. rvGamePlayback::~rvGamePlayback( void )
  61. {
  62.     declManager->FinishPlayback( mPlayback );
  63.     delete mClipModel;
  64.  
  65.     common->Printf( "Stopping playback play/record\n" );
  66. }
  67.  
  68. void rvGamePlayback::RecordData( const usercmd_t &cmd, idEntity *source )
  69. {
  70.     idPlayer            *player;
  71.     trace_t                trace;
  72.     idMat3                axis;
  73.     idVec3                start, end;
  74.     rvDeclPlaybackData    info;
  75.  
  76.     info.Init();
  77.  
  78.     switch( g_recordPlayback.GetInteger() )
  79.     {
  80.     case 1:
  81.         info.SetPosition( source->GetPhysics()->GetOrigin() );
  82.         info.SetAngles( source->GetPhysics()->GetAxis().ToAngles() );
  83.         break;
  84.  
  85.     case 2:
  86.         gameLocal.GetPlayerView( start, axis );
  87.         
  88.         end = start + axis[0] * RECORD_STATE_TRACE_LEN;
  89.  
  90.         gameLocal.Translation( gameLocal.GetLocalPlayer(), trace, start, end, mClipModel, mat3_identity, CONTENTS_SOLID | CONTENTS_RENDERMODEL, source );
  91.  
  92.         if( trace.fraction != 1.0f ) 
  93.         {
  94.             info.SetPosition( trace.endpos );
  95.             info.SetAngles( trace.c.normal.ToAngles() );
  96.         }
  97.         break;
  98.  
  99.     case 3:
  100.         assert( source->IsType( idPlayer::GetClassType() ) );
  101.         if( source->IsType( idPlayer::GetClassType() ) )
  102.         {
  103.             player = static_cast<idPlayer *>( source );
  104.             info.SetPosition( player->GetEyePosition() ); 
  105.             info.SetAngles( source->GetPhysics()->GetAxis().ToAngles() );
  106.         }
  107.         break;
  108.     }
  109.  
  110.     // Record buttons
  111.     info.SetButtons( cmd.buttons );
  112.  
  113.     // Record impulses
  114.     if( ( cmd.flags & UCF_IMPULSE_SEQUENCE ) != ( mOldFlags & UCF_IMPULSE_SEQUENCE ) )
  115.     {
  116.         info.SetImpulse( cmd.impulse );
  117.     }
  118.     else
  119.     {
  120.         info.SetImpulse( 0 );
  121.     }
  122.     mOldFlags = cmd.flags;
  123.  
  124.     declManager->SetPlaybackData( mPlayback, gameLocal.time - mStartTime, -1, &info );
  125. }
  126.  
  127. // ================================================================================================
  128.  
  129. void idGameEdit::DrawPlaybackDebugInfo( void )
  130. {
  131.     int                        duration, time;
  132.     rvDeclPlaybackData        pbd, pbdOld;
  133.     const rvDeclPlayback    *pb;
  134.  
  135.     pb = declManager->PlaybackByIndex( g_currentPlayback.GetInteger(), true );
  136.     if( pb )
  137.     {
  138.         duration = SEC2MS( pb->GetDuration() );
  139.         pbd.Init();
  140.         pbdOld.Init();
  141.  
  142.         declManager->GetPlaybackData( pb, -1, 0, 0, &pbdOld );
  143.         for( time = gameLocal.GetMSec(); time < duration; time += gameLocal.GetMSec() * g_showPlayback.GetInteger() )
  144.         {
  145.             declManager->GetPlaybackData( pb, -1, time, time, &pbd );
  146.             gameRenderWorld->DebugArrow( colorGreen, pbdOld.GetPosition(), pbd.GetPosition(), 2 );
  147.             pbdOld = pbd;
  148.         }
  149.  
  150.         gameRenderWorld->DebugBounds( colorRed, pb->GetBounds(), pb->GetOrigin() );
  151.     }
  152. }
  153.  
  154. void idGameEdit::RecordPlayback( const usercmd_t &cmd, idEntity *source )
  155. {
  156.     // Not recording - so instantly exit
  157.     if( !g_recordPlayback.GetInteger() && !gamePlayback ) 
  158.     {
  159.         return;
  160.     }
  161.  
  162.     if( !gamePlayback )
  163.     {
  164.         gamePlayback = new rvGamePlayback();
  165.     }
  166.  
  167.     if( g_recordPlayback.GetInteger() )
  168.     {
  169.         gamePlayback->RecordData( cmd, source );
  170.     }
  171.     else
  172.     {
  173.         delete gamePlayback;
  174.         gamePlayback = NULL;
  175.     }
  176. }
  177.  
  178. // ================================================================================================
  179.  
  180. bool idGameEdit::PlayPlayback( void )
  181. {
  182.     // Not playing - so instantly exit
  183.     if( !g_playPlayback.GetInteger() && !playbackCamera ) 
  184.     {
  185.         return( false );
  186.     }
  187.  
  188.     if( !playbackCamera )
  189.     {
  190.         playbackCamera = static_cast<rvCameraPlayback *>( gameLocal.SpawnEntityType( rvCameraPlayback::GetClassType() ) );
  191.         SetCamera( playbackCamera );
  192.  
  193.         common->Printf( "Starting playback play\n" );
  194.     }
  195.  
  196.     if( g_currentPlayback.IsModified() )
  197.     {
  198.         // Spawn is a misnomer - it should be init with new data
  199.         playbackCamera->Spawn();
  200.         g_currentPlayback.ClearModified();
  201.     }
  202.  
  203.     if( !g_playPlayback.GetInteger() )
  204.     {
  205.         playbackCamera->PostEventMS( &EV_Remove, 0 );
  206.         playbackCamera = NULL;
  207.         SetCamera( NULL );
  208.     }
  209.  
  210.     return( true );
  211. }
  212.  
  213. // ================================================================================================
  214.  
  215. void idGameEdit::ShutdownPlaybacks( void )
  216. {
  217.     g_recordPlayback.SetInteger( 0 );
  218.     g_playPlayback.SetInteger( 0 );
  219.  
  220.     if( gamePlayback )
  221.     {
  222.         delete gamePlayback;
  223.         gamePlayback = NULL;
  224.     }
  225.  
  226.     if( playbackCamera )
  227.     {
  228.         playbackCamera->PostEventMS( &EV_Remove, 0 );
  229.         playbackCamera = NULL;
  230.         SetCamera( NULL );
  231.     }
  232. }
  233.  
  234. // ================================================================================================
  235.  
  236. /*
  237. ============
  238. rvPlaybackDriver::Start
  239.  
  240. Start a new playback automatically blending with the old playback (if any) over numFrames
  241. ============
  242. */
  243. bool rvPlaybackDriver::Start( const char *playback, idEntity *owner, int flags, int numFrames )
  244. {
  245.     idVec3    startPos;
  246.  
  247.     if( !idStr::Length( playback ) )
  248.     {
  249.         mPlaybackDecl = NULL;
  250.         mOldPlaybackDecl = NULL;
  251.         return( true );
  252.     }
  253.  
  254.     const rvDeclPlayback *pb = declManager->FindPlayback( playback );
  255.  
  256.     if( g_showPlayback.GetInteger() )
  257.     {
  258.         common->Printf( "Starting playback: %s\n", pb->GetName() );
  259.     }
  260.  
  261.     mOldPlaybackDecl = mPlaybackDecl;
  262.     mOldFlags = mFlags;
  263.     mOldStartTime = mStartTime;
  264.     mOldOffset = mOffset;
  265.  
  266.     mPlaybackDecl = pb;
  267.     mFlags = flags;
  268.     mStartTime = gameLocal.time;
  269.     mOffset.Zero();
  270.  
  271.     if( flags & PBFL_RELATIVE_POSITION )
  272.     {
  273.         mOffset = owner->GetPhysics()->GetOrigin() - pb->GetOrigin();
  274.     }
  275.  
  276.     mTransitionTime = numFrames * gameLocal.GetMSec();
  277.     return( true );
  278. }
  279.  
  280. /*
  281. ============
  282. PlaybackCallback
  283.  
  284. Called whenever a button up or down, or an impulse event is found while getting the playback data
  285. ============
  286. */
  287. void PlaybackCallback( int type, float time, const void *data )
  288. {
  289.     const rvDeclPlaybackData *pbd = ( const rvDeclPlaybackData * )data;
  290.     idEntity *ent = pbd->GetEntity();
  291.  
  292.     ent->PostEventSec( &EV_PlaybackCallback, time, type, pbd->GetChanged(), pbd->GetImpulse() );
  293. }
  294.  
  295. /*
  296. ============
  297. rvPlaybackDriver::UpdateFrame
  298.  
  299. Blend two playbacks together 
  300. ============
  301. */
  302. bool rvPlaybackDriver::UpdateFrame( idEntity *ent, rvDeclPlaybackData &out )
  303. {
  304.     rvDeclPlaybackData    pbd, oldPbd;
  305.     float                blend, invBlend;
  306.     idStr                ret;
  307.     bool                expired, oldExpired;
  308.     
  309.     // Get the current playback position
  310.     pbd.Init();
  311.     pbd.SetCallback( ent, PlaybackCallback );
  312.     expired = declManager->GetPlaybackData( mPlaybackDecl, mFlags, gameLocal.time - mStartTime, mLastTime - mStartTime, &pbd );
  313.     pbd.SetPosition( pbd.GetPosition() + mOffset );
  314.  
  315.     // Get the playback data we are merging from
  316.     oldPbd.Init();
  317.     oldExpired = declManager->GetPlaybackData( mOldPlaybackDecl, mOldFlags, gameLocal.time - mOldStartTime, gameLocal.time - mOldStartTime, &oldPbd );
  318.     oldPbd.SetPosition( oldPbd.GetPosition() + mOldOffset );
  319.  
  320.     mLastTime = gameLocal.time;
  321.  
  322.     if( g_showPlayback.GetInteger() && mPlaybackDecl )
  323.     {
  324.         common->Printf( "Running playback: %s at %.1f\n", mPlaybackDecl->GetName(), MS2SEC( gameLocal.time - mStartTime ) );
  325.     }
  326.  
  327.     // Fully merged - so delete the old one
  328.     if( gameLocal.time > mStartTime + mTransitionTime )
  329.     {
  330.         oldExpired = true;
  331.     }
  332.  
  333.     // Interpolate the result
  334.     if( expired && oldExpired )
  335.     {
  336.         out.Init();
  337.         mPlaybackDecl = NULL;
  338.         mOldPlaybackDecl = NULL;
  339.     }
  340.     else if( !expired && oldExpired )
  341.     {
  342.         out = pbd;
  343.         mOldPlaybackDecl = NULL;
  344.     }
  345.     else if( expired && !oldExpired )
  346.     {
  347.         out = oldPbd;
  348.         mPlaybackDecl = NULL;
  349.     }
  350.     else
  351.     {
  352.         // Linear zero to one
  353.         blend = idMath::ClampFloat( 0.0f, 1.0f, ( gameLocal.time - mStartTime ) / ( float )mTransitionTime );
  354.         
  355.         // Sinusoidal
  356.         blend = idMath::Sin( blend * idMath::HALF_PI );
  357.         invBlend = 1.0f - blend;
  358.  
  359.         out.SetPosition( blend * pbd.GetPosition() + invBlend * oldPbd.GetPosition() );
  360.         out.SetAngles( blend * pbd.GetAngles() + invBlend * oldPbd.GetAngles() );
  361.         out.SetButtons( pbd.GetButtons() );
  362.         out.SetImpulse( pbd.GetImpulse() );
  363.     }
  364.  
  365.     return( expired );
  366. }
  367.  
  368. // cnicholson: Begin  Added save/restore functionality
  369. /*
  370. ============
  371. rvPlaybackDriver::Save
  372.  
  373. Save all member vars for save/load games
  374. ============
  375. */
  376. void rvPlaybackDriver::Save( idSaveGame *savefile ) const {
  377.  
  378.     savefile->WriteInt( mLastTime );        // cnicholson: Added unsaved var
  379.     savefile->WriteInt( mTransitionTime );    // cnicholson: Added unsaved var
  380.  
  381.     savefile->WriteInt( mStartTime );        // cnicholson: Added unsaved var
  382.     savefile->WriteInt( mFlags );            // cnicholson: Added unsaved var
  383.     // TOSAVE: const rvDeclPlayback    *mPlaybackDecl;
  384.     savefile->WriteVec3( mOffset );            // cnicholson: Added unsaved var
  385.  
  386.     savefile->WriteInt( mOldStartTime );    // cnicholson: Added unsaved var
  387.     savefile->WriteInt( mOldFlags );        // cnicholson: Added unsaved var
  388.     // TOSAVE: const rvDeclPlayback    *mOldPlaybackDecl;
  389.     savefile->WriteVec3( mOldOffset );        // cnicholson: Added unsaved var
  390. }
  391.  
  392. /*
  393. ============
  394. rvPlaybackDriver::Restore
  395.  
  396. Restore all member vars for save/load games
  397. ============
  398. */
  399. void rvPlaybackDriver::Restore( idRestoreGame *savefile ) {
  400.  
  401.     savefile->ReadInt( mLastTime );            // cnicholson: Added unrestored var
  402.     savefile->ReadInt( mTransitionTime );    // cnicholson: Added unrestored var
  403.  
  404.     savefile->ReadInt( mStartTime );        // cnicholson: Added unrestored var
  405.     savefile->ReadInt( mFlags );            // cnicholson: Added unrestored var
  406.     // TOSAVE: const rvDeclPlayback    *mPlaybackDecl;
  407.     savefile->ReadVec3( mOffset );            // cnicholson: Added unrestored var
  408.  
  409.     savefile->ReadInt( mOldStartTime );        // cnicholson: Added unrestored var
  410.     savefile->ReadInt( mOldFlags );            // cnicholson: Added unrestored var
  411.     // TOSAVE: const rvDeclPlayback    *mOldPlaybackDecl;
  412.     savefile->ReadVec3( mOldOffset );        // cnicholson: Added unrestored var
  413. }
  414. // cnicholson: End  Added save/restore functionality
  415.  
  416. // end
  417.  
  418.