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

  1. #include "../../idlib/precompiled.h"
  2. #pragma hdrstop
  3.  
  4. #include "../Game_local.h"
  5. #include "../Weapon.h"
  6. #include "../client/ClientEffect.h"
  7.  
  8. #ifndef __GAME_PROJECTILE_H__
  9. #include "../Projectile.h"
  10. #endif
  11.  
  12. class rvWeaponRocketLauncher : public rvWeapon {
  13. public:
  14.  
  15.     CLASS_PROTOTYPE( rvWeaponRocketLauncher );
  16.  
  17.     rvWeaponRocketLauncher ( void );
  18.     ~rvWeaponRocketLauncher ( void );
  19.  
  20.     virtual void            Spawn                ( void );
  21.     virtual void            Think                ( void );
  22.  
  23.     void                    Save( idSaveGame *saveFile ) const;
  24.     void                    Restore( idRestoreGame *saveFile );
  25.     void                    PreSave                ( void );
  26.     void                    PostSave            ( void );
  27.  
  28.  
  29. #ifdef _XENON
  30.     virtual bool        AllowAutoAim            ( void ) const { return false; }
  31. #endif
  32.  
  33. protected:
  34.  
  35.     virtual void            OnLaunchProjectile    ( idProjectile* proj );
  36.  
  37.     void                    SetRocketState        ( const char* state, int blendFrames );
  38.  
  39.     rvClientEntityPtr<rvClientEffect>    guideEffect;
  40.     idList< idEntityPtr<idEntity> >        guideEnts;
  41.     float                                guideSpeedSlow;
  42.     float                                guideSpeedFast;
  43.     float                                guideRange;
  44.     float                                guideAccelTime;
  45.  
  46.     rvStateThread                        rocketThread;
  47.  
  48.     float                                reloadRate;
  49.  
  50.     bool                                idleEmpty;
  51.  
  52. private:
  53.  
  54.     stateResult_t        State_Idle                ( const stateParms_t& parms );
  55.     stateResult_t        State_Fire                ( const stateParms_t& parms );
  56.     stateResult_t        State_Raise                ( const stateParms_t& parms );
  57.     stateResult_t        State_Lower                ( const stateParms_t& parms );
  58.     
  59.     stateResult_t        State_Rocket_Idle        ( const stateParms_t& parms );
  60.     stateResult_t        State_Rocket_Reload        ( const stateParms_t& parms );
  61.     
  62.     stateResult_t        Frame_AddToClip            ( const stateParms_t& parms );
  63.     
  64.     CLASS_STATES_PROTOTYPE ( rvWeaponRocketLauncher );
  65. };
  66.  
  67. CLASS_DECLARATION( rvWeapon, rvWeaponRocketLauncher )
  68. END_CLASS
  69.  
  70. /*
  71. ================
  72. rvWeaponRocketLauncher::rvWeaponRocketLauncher
  73. ================
  74. */
  75. rvWeaponRocketLauncher::rvWeaponRocketLauncher ( void ) {
  76. }
  77.  
  78. /*
  79. ================
  80. rvWeaponRocketLauncher::~rvWeaponRocketLauncher
  81. ================
  82. */
  83. rvWeaponRocketLauncher::~rvWeaponRocketLauncher ( void ) {
  84.     if ( guideEffect ) {
  85.         guideEffect->Stop();
  86.     }
  87. }
  88.  
  89. /*
  90. ================
  91. rvWeaponRocketLauncher::Spawn
  92. ================
  93. */
  94. void rvWeaponRocketLauncher::Spawn ( void ) {
  95.     float f;
  96.  
  97.     idleEmpty = false;
  98.     
  99.     spawnArgs.GetFloat ( "lockRange", "0", guideRange );
  100.  
  101.     spawnArgs.GetFloat ( "lockSlowdown", ".25", f );
  102.     attackDict.GetFloat ( "speed", "0", guideSpeedFast );
  103.     guideSpeedSlow = guideSpeedFast * f;
  104.     
  105.     reloadRate = SEC2MS ( spawnArgs.GetFloat ( "reloadRate", ".8" ) );
  106.     
  107.     guideAccelTime = SEC2MS ( spawnArgs.GetFloat ( "lockAccelTime", ".25" ) );
  108.     
  109.     // Start rocket thread
  110.     rocketThread.SetName ( viewModel->GetName ( ) );
  111.     rocketThread.SetOwner ( this );
  112.  
  113.     // Adjust reload animations to match the fire rate
  114.     idAnim* anim;
  115.     int        animNum;
  116.     float    rate;
  117.     animNum = viewModel->GetAnimator()->GetAnim ( "reload" );
  118.     if ( animNum ) {
  119.         anim = (idAnim*)viewModel->GetAnimator()->GetAnim ( animNum );
  120.         rate = (float)anim->Length() / (float)SEC2MS(spawnArgs.GetFloat ( "reloadRate", ".8" ));
  121.         anim->SetPlaybackRate ( rate );
  122.     }
  123.  
  124.     animNum = viewModel->GetAnimator()->GetAnim ( "reload_empty" );
  125.     if ( animNum ) {
  126.         anim = (idAnim*)viewModel->GetAnimator()->GetAnim ( animNum );
  127.         rate = (float)anim->Length() / (float)SEC2MS(spawnArgs.GetFloat ( "reloadRate", ".8" ));
  128.         anim->SetPlaybackRate ( rate );
  129.     }
  130.  
  131.     SetState ( "Raise", 0 );    
  132.     SetRocketState ( "Rocket_Idle", 0 );
  133. }
  134.  
  135. /*
  136. ================
  137. rvWeaponRocketLauncher::Think
  138. ================
  139. */
  140. void rvWeaponRocketLauncher::Think ( void ) {    
  141.     trace_t    tr;
  142.     int        i;
  143.  
  144.     rocketThread.Execute ( );
  145.  
  146.     // Let the real weapon think first
  147.     rvWeapon::Think ( );
  148.  
  149.     // IF no guide range is set then we dont have the mod yet    
  150.     if ( !guideRange ) {
  151.         return;
  152.     }
  153.     
  154.     if ( !wsfl.zoom ) {
  155.         if ( guideEffect ) {
  156.             guideEffect->Stop();
  157.             guideEffect = NULL;
  158.         }
  159.  
  160.         for ( i = guideEnts.Num() - 1; i >= 0; i -- ) {
  161.             idGuidedProjectile* proj = static_cast<idGuidedProjectile*>(guideEnts[i].GetEntity());
  162.             if ( !proj || proj->IsHidden ( ) ) {
  163.                 guideEnts.RemoveIndex ( i );
  164.                 continue;
  165.             }
  166.             
  167.             // If the rocket is still guiding then stop the guide and slow it down
  168.             if ( proj->GetGuideType ( ) != idGuidedProjectile::GUIDE_NONE ) {
  169.                 proj->CancelGuide ( );                
  170.                 proj->SetSpeed ( guideSpeedFast, (1.0f - (proj->GetSpeed ( ) - guideSpeedSlow) / (guideSpeedFast - guideSpeedSlow)) * guideAccelTime );
  171.             }
  172.         }
  173.  
  174.         return;
  175.     }
  176.                         
  177.     // Cast a ray out to the lock range
  178. // RAVEN BEGIN
  179. // ddynerman: multiple clip worlds
  180.     gameLocal.TracePoint(    owner, tr, 
  181.                             playerViewOrigin, 
  182.                             playerViewOrigin + playerViewAxis[0] * guideRange, 
  183.                             MASK_SHOT_RENDERMODEL, owner );
  184. // RAVEN END
  185.     
  186.     for ( i = guideEnts.Num() - 1; i >= 0; i -- ) {
  187.         idGuidedProjectile* proj = static_cast<idGuidedProjectile*>(guideEnts[i].GetEntity());
  188.         if ( !proj || proj->IsHidden() ) {
  189.             guideEnts.RemoveIndex ( i );
  190.             continue;
  191.         }
  192.         
  193.         // If the rocket isnt guiding yet then adjust its speed back to normal
  194.         if ( proj->GetGuideType ( ) == idGuidedProjectile::GUIDE_NONE ) {
  195.             proj->SetSpeed ( guideSpeedSlow, (proj->GetSpeed ( ) - guideSpeedSlow) / (guideSpeedFast - guideSpeedSlow) * guideAccelTime );
  196.         }
  197.         proj->GuideTo ( tr.endpos );                
  198.     }
  199.     
  200.     if ( !guideEffect ) {
  201.         guideEffect = gameLocal.PlayEffect ( gameLocal.GetEffect ( spawnArgs, "fx_guide" ), tr.endpos, tr.c.normal.ToMat3(), true, vec3_origin, true );
  202.     } else {
  203.         guideEffect->SetOrigin ( tr.endpos );
  204.         guideEffect->SetAxis ( tr.c.normal.ToMat3() );
  205.     }
  206. }
  207.  
  208. /*
  209. ================
  210. rvWeaponRocketLauncher::OnLaunchProjectile
  211. ================
  212. */
  213. void rvWeaponRocketLauncher::OnLaunchProjectile ( idProjectile* proj ) {
  214.     rvWeapon::OnLaunchProjectile(proj);
  215.  
  216.     // Double check that its actually a guided projectile
  217.     if ( !proj || !proj->IsType ( idGuidedProjectile::GetClassType() ) ) {
  218.         return;
  219.     }
  220.  
  221.     // Launch the projectile
  222.     idEntityPtr<idEntity> ptr;
  223.     ptr = proj;
  224.     guideEnts.Append ( ptr );    
  225. }
  226.  
  227. /*
  228. ================
  229. rvWeaponRocketLauncher::SetRocketState
  230. ================
  231. */
  232. void rvWeaponRocketLauncher::SetRocketState ( const char* state, int blendFrames ) {
  233.     rocketThread.SetState ( state, blendFrames );
  234. }
  235.  
  236. /*
  237. =====================
  238. rvWeaponRocketLauncher::Save
  239. =====================
  240. */
  241. void rvWeaponRocketLauncher::Save( idSaveGame *saveFile ) const {
  242.     saveFile->WriteObject( guideEffect );
  243.  
  244.     idEntity* ent = NULL;
  245.     saveFile->WriteInt( guideEnts.Num() ); 
  246.     for( int ix = 0; ix < guideEnts.Num(); ++ix ) {
  247.         ent = guideEnts[ ix ].GetEntity();
  248.         if( ent ) {
  249.             saveFile->WriteObject( ent );
  250.         }
  251.     }
  252.     
  253.     saveFile->WriteFloat( guideSpeedSlow );
  254.     saveFile->WriteFloat( guideSpeedFast );
  255.     saveFile->WriteFloat( guideRange );
  256.     saveFile->WriteFloat( guideAccelTime );
  257.     
  258.     saveFile->WriteFloat ( reloadRate );
  259.     
  260.     rocketThread.Save( saveFile );
  261. }
  262.  
  263. /*
  264. =====================
  265. rvWeaponRocketLauncher::Restore
  266. =====================
  267. */
  268. void rvWeaponRocketLauncher::Restore( idRestoreGame *saveFile ) {
  269.     int numEnts = 0;
  270.     idEntity* ent = NULL;
  271.     rvClientEffect* clientEffect = NULL;
  272.  
  273.     saveFile->ReadObject( reinterpret_cast<idClass *&>(clientEffect) );
  274.     guideEffect = clientEffect;
  275.     
  276.     saveFile->ReadInt( numEnts );
  277.     guideEnts.Clear();
  278.     guideEnts.SetNum( numEnts );
  279.     for( int ix = 0; ix < numEnts; ++ix ) {
  280.         saveFile->ReadObject( reinterpret_cast<idClass *&>(ent) );
  281.         guideEnts[ ix ] = ent;
  282.     }
  283.     
  284.     saveFile->ReadFloat( guideSpeedSlow );
  285.     saveFile->ReadFloat( guideSpeedFast );
  286.     saveFile->ReadFloat( guideRange );
  287.     saveFile->ReadFloat( guideAccelTime );
  288.     
  289.     saveFile->ReadFloat ( reloadRate );
  290.     
  291.     rocketThread.Restore( saveFile, this );    
  292. }
  293.  
  294. /*
  295. ================
  296. rvWeaponRocketLauncher::PreSave
  297. ================
  298. */
  299. void rvWeaponRocketLauncher::PreSave ( void ) {
  300. }
  301.  
  302. /*
  303. ================
  304. rvWeaponRocketLauncher::PostSave
  305. ================
  306. */
  307. void rvWeaponRocketLauncher::PostSave ( void ) {
  308. }
  309.  
  310.  
  311. /*
  312. ===============================================================================
  313.  
  314.     States 
  315.  
  316. ===============================================================================
  317. */
  318.  
  319. CLASS_STATES_DECLARATION ( rvWeaponRocketLauncher )
  320.     STATE ( "Idle",                rvWeaponRocketLauncher::State_Idle)
  321.     STATE ( "Fire",                rvWeaponRocketLauncher::State_Fire )
  322.     STATE ( "Raise",            rvWeaponRocketLauncher::State_Raise )
  323.     STATE ( "Lower",            rvWeaponRocketLauncher::State_Lower )
  324.  
  325.     STATE ( "Rocket_Idle",        rvWeaponRocketLauncher::State_Rocket_Idle )
  326.     STATE ( "Rocket_Reload",    rvWeaponRocketLauncher::State_Rocket_Reload )
  327.     
  328.     STATE ( "AddToClip",        rvWeaponRocketLauncher::Frame_AddToClip )
  329. END_CLASS_STATES
  330.  
  331.  
  332. /*
  333. ================
  334. rvWeaponRocketLauncher::State_Raise
  335.  
  336. Raise the weapon
  337. ================
  338. */
  339. stateResult_t rvWeaponRocketLauncher::State_Raise ( const stateParms_t& parms ) {
  340.     enum {
  341.         STAGE_INIT,
  342.         STAGE_WAIT,
  343.     };    
  344.     switch ( parms.stage ) {
  345.         // Start the weapon raising
  346.         case STAGE_INIT:
  347.             SetStatus ( WP_RISING );
  348.             PlayAnim( ANIMCHANNEL_LEGS, "raise", 0 );
  349.             return SRESULT_STAGE ( STAGE_WAIT );
  350.             
  351.         case STAGE_WAIT:
  352.             if ( AnimDone ( ANIMCHANNEL_LEGS, 4 ) ) {
  353.                 SetState ( "Idle", 4 );
  354.                 return SRESULT_DONE;
  355.             }
  356.             if ( wsfl.lowerWeapon ) {
  357.                 SetState ( "Lower", 4 );
  358.                 return SRESULT_DONE;
  359.             }
  360.             return SRESULT_WAIT;
  361.     }
  362.     return SRESULT_ERROR;
  363. }
  364.  
  365. /*
  366. ================
  367. rvWeaponRocketLauncher::State_Lower
  368.  
  369. Lower the weapon
  370. ================
  371. */
  372. stateResult_t rvWeaponRocketLauncher::State_Lower ( const stateParms_t& parms ) {    
  373.     enum {
  374.         STAGE_INIT,
  375.         STAGE_WAIT,
  376.         STAGE_WAITRAISE
  377.     };    
  378.     switch ( parms.stage ) {
  379.         case STAGE_INIT:
  380.             SetStatus ( WP_LOWERING );
  381.             PlayAnim ( ANIMCHANNEL_LEGS, "putaway", parms.blendFrames );
  382.             return SRESULT_STAGE(STAGE_WAIT);
  383.             
  384.         case STAGE_WAIT:
  385.             if ( AnimDone ( ANIMCHANNEL_LEGS, 0 ) ) {
  386.                 SetStatus ( WP_HOLSTERED );
  387.                 return SRESULT_STAGE(STAGE_WAITRAISE);
  388.             }
  389.             return SRESULT_WAIT;
  390.         
  391.         case STAGE_WAITRAISE:
  392.             if ( wsfl.raiseWeapon ) {
  393.                 SetState ( "Raise", 0 );
  394.                 return SRESULT_DONE;
  395.             }
  396.             return SRESULT_WAIT;
  397.     }
  398.     return SRESULT_ERROR;
  399. }
  400.  
  401. /*
  402. ================
  403. rvWeaponRocketLauncher::State_Idle
  404. ================
  405. */
  406. stateResult_t rvWeaponRocketLauncher::State_Idle( const stateParms_t& parms ) {
  407.     enum {
  408.         STAGE_INIT,
  409.         STAGE_WAIT,
  410.     };    
  411.     switch ( parms.stage ) {
  412.         case STAGE_INIT:
  413.             if ( !AmmoAvailable ( ) ) {
  414.                 SetStatus ( WP_OUTOFAMMO );
  415.             } else {
  416.                 SetStatus ( WP_READY );
  417.             }
  418.         
  419.             PlayCycle( ANIMCHANNEL_LEGS, "idle", parms.blendFrames );
  420.             return SRESULT_STAGE ( STAGE_WAIT );
  421.         
  422.         case STAGE_WAIT:
  423.             if ( wsfl.lowerWeapon ) {
  424.                 SetState ( "Lower", 4 );
  425.                 return SRESULT_DONE;
  426.             }        
  427.             if ( gameLocal.time > nextAttackTime && wsfl.attack && ( gameLocal.isClient || AmmoInClip ( ) ) ) {
  428.                 SetState ( "Fire", 2 );
  429.                 return SRESULT_DONE;
  430.             }
  431.             return SRESULT_WAIT;
  432.     }
  433.     return SRESULT_ERROR;
  434. }
  435.  
  436. /*
  437. ================
  438. rvWeaponRocketLauncher::State_Fire
  439. ================
  440. */
  441. stateResult_t rvWeaponRocketLauncher::State_Fire ( const stateParms_t& parms ) {
  442.     enum {
  443.         STAGE_INIT,
  444.         STAGE_WAIT,
  445.     };    
  446.     switch ( parms.stage ) {
  447.         case STAGE_INIT:
  448.             nextAttackTime = gameLocal.time + (fireRate * owner->PowerUpModifier ( PMOD_FIRERATE ));        
  449.             Attack ( false, 1, spread, 0, 1.0f );
  450.             PlayAnim ( ANIMCHANNEL_LEGS, "fire", parms.blendFrames );    
  451.             return SRESULT_STAGE ( STAGE_WAIT );
  452.     
  453.         case STAGE_WAIT:            
  454.             if ( wsfl.attack && gameLocal.time >= nextAttackTime && ( gameLocal.isClient || AmmoInClip ( ) ) && !wsfl.lowerWeapon ) {
  455.                 SetState ( "Fire", 0 );
  456.                 return SRESULT_DONE;
  457.             }
  458.             if ( gameLocal.time > nextAttackTime && AnimDone ( ANIMCHANNEL_LEGS, 4 ) ) {
  459.                 SetState ( "Idle", 4 );
  460.                 return SRESULT_DONE;
  461.             }
  462.             return SRESULT_WAIT;
  463.     }
  464.     return SRESULT_ERROR;
  465. }
  466.  
  467. /*
  468. ================
  469. rvWeaponRocketLauncher::State_Rocket_Idle
  470. ================
  471. */
  472. stateResult_t rvWeaponRocketLauncher::State_Rocket_Idle ( const stateParms_t& parms ) {
  473.     enum {
  474.         STAGE_INIT,
  475.         STAGE_WAIT,
  476.         STAGE_WAITEMPTY,
  477.     };    
  478.     
  479.     switch ( parms.stage ) {
  480.         case STAGE_INIT:
  481.             if ( AmmoAvailable ( ) <= AmmoInClip() ) {
  482.                 PlayAnim( ANIMCHANNEL_TORSO, "idle_empty", parms.blendFrames );
  483.                 idleEmpty = true;
  484.             } else { 
  485.                 PlayAnim( ANIMCHANNEL_TORSO, "idle", parms.blendFrames );
  486.             }
  487.             return SRESULT_STAGE ( STAGE_WAIT );
  488.         
  489.         case STAGE_WAIT:
  490.             if ( AmmoAvailable ( ) > AmmoInClip() ) {
  491.                 if ( idleEmpty ) {
  492.                     SetRocketState ( "Rocket_Reload", 0 );
  493.                     return SRESULT_DONE;
  494.                 } else if ( ClipSize ( ) > 1 ) {
  495.                     if ( gameLocal.time > nextAttackTime && AmmoInClip ( ) < ClipSize( ) ) {
  496.                         if ( !AmmoInClip() || !wsfl.attack ) {
  497.                             SetRocketState ( "Rocket_Reload", 0 );
  498.                             return SRESULT_DONE;
  499.                         }
  500.                     }
  501.                 } else {
  502.                     if ( AmmoInClip ( ) == 0 ) {
  503.                         SetRocketState ( "Rocket_Reload", 0 );
  504.                         return SRESULT_DONE;
  505.                     }                
  506.                 }
  507.             }
  508.             return SRESULT_WAIT;
  509.     }
  510.     return SRESULT_ERROR;
  511. }
  512.  
  513. /*
  514. ================
  515. rvWeaponRocketLauncher::State_Rocket_Reload
  516. ================
  517. */
  518. stateResult_t rvWeaponRocketLauncher::State_Rocket_Reload ( const stateParms_t& parms ) {
  519.     enum {
  520.         STAGE_INIT,
  521.         STAGE_WAIT,
  522.     };    
  523.     
  524.     switch ( parms.stage ) {
  525.         case STAGE_INIT: {
  526.             const char* animName;
  527.             int            animNum;
  528.  
  529.             if ( idleEmpty ) {
  530.                 animName = "ammo_pickup";
  531.                 idleEmpty = false;
  532.             } else if ( AmmoAvailable ( ) == AmmoInClip( ) + 1 ) {
  533.                 animName = "reload_empty";
  534.             } else {
  535.                 animName = "reload";
  536.             }
  537.             
  538.             animNum = viewModel->GetAnimator()->GetAnim ( animName );
  539.             if ( animNum ) {
  540.                 idAnim* anim;
  541.                 anim = (idAnim*)viewModel->GetAnimator()->GetAnim ( animNum );                
  542.                 anim->SetPlaybackRate ( (float)anim->Length() / (reloadRate * owner->PowerUpModifier ( PMOD_FIRERATE )) );
  543.             }
  544.  
  545.             PlayAnim( ANIMCHANNEL_TORSO, animName, parms.blendFrames );                
  546.  
  547.             return SRESULT_STAGE ( STAGE_WAIT );
  548.         }
  549.         
  550.         case STAGE_WAIT:
  551.             if ( AnimDone ( ANIMCHANNEL_TORSO, 0 ) ) {                
  552.                 if ( !wsfl.attack && gameLocal.time > nextAttackTime && AmmoInClip ( ) < ClipSize( ) && AmmoAvailable() > AmmoInClip() ) {
  553.                     SetRocketState ( "Rocket_Reload", 0 );
  554.                 } else {
  555.                     SetRocketState ( "Rocket_Idle", 0 );
  556.                 }
  557.                 return SRESULT_DONE;
  558.             }
  559.             /*
  560.             if ( gameLocal.isMultiplayer && gameLocal.time > nextAttackTime && wsfl.attack ) {
  561.                 if ( AmmoInClip ( ) == 0 )
  562.                 {
  563.                     AddToClip ( ClipSize() );
  564.                 }
  565.                 SetRocketState ( "Rocket_Idle", 0 );
  566.                 return SRESULT_DONE;
  567.             }
  568.             */
  569.             return SRESULT_WAIT;
  570.     }
  571.     return SRESULT_ERROR;
  572. }
  573.  
  574. /*
  575. ================
  576. rvWeaponRocketLauncher::Frame_AddToClip
  577. ================
  578. */
  579. stateResult_t rvWeaponRocketLauncher::Frame_AddToClip ( const stateParms_t& parms ) {
  580.     AddToClip ( 1 );
  581.     return SRESULT_OK;
  582. }
  583.  
  584.