quake4-sdk/source/mpgame/weapon/WeaponHyperblaster.cpp

296 lines
6.8 KiB
C++

#include "../../idlib/precompiled.h"
#pragma hdrstop
#include "../Game_local.h"
#include "../Weapon.h"
const int HYPERBLASTER_SPARM_BATTERY = 6;
const int HYPERBLASTER_SPIN_SPEED = 300;
class rvWeaponHyperblaster : public rvWeapon {
public:
CLASS_PROTOTYPE( rvWeaponHyperblaster );
rvWeaponHyperblaster ( void );
virtual void Spawn ( void );
void Save ( idSaveGame *savefile ) const;
void Restore ( idRestoreGame *savefile );
void PreSave ( void );
void PostSave ( void );
protected:
jointHandle_t jointBatteryView;
bool spinning;
void SpinUp ( void );
void SpinDown ( void );
private:
stateResult_t State_Idle ( const stateParms_t& parms );
stateResult_t State_Fire ( const stateParms_t& parms );
stateResult_t State_Reload ( const stateParms_t& parms );
CLASS_STATES_PROTOTYPE ( rvWeaponHyperblaster );
};
CLASS_DECLARATION( rvWeapon, rvWeaponHyperblaster )
END_CLASS
/*
================
rvWeaponHyperblaster::rvWeaponHyperblaster
================
*/
rvWeaponHyperblaster::rvWeaponHyperblaster ( void ) {
}
/*
================
rvWeaponHyperblaster::Spawn
================
*/
void rvWeaponHyperblaster::Spawn ( void ) {
jointBatteryView = viewAnimator->GetJointHandle ( spawnArgs.GetString ( "joint_view_battery" ) );
spinning = false;
SetState ( "Raise", 0 );
}
/*
================
rvWeaponHyperblaster::Save
================
*/
void rvWeaponHyperblaster::Save ( idSaveGame *savefile ) const {
savefile->WriteJoint ( jointBatteryView );
savefile->WriteBool ( spinning );
}
/*
================
rvWeaponHyperblaster::Restore
================
*/
void rvWeaponHyperblaster::Restore ( idRestoreGame *savefile ) {
savefile->ReadJoint ( jointBatteryView );
savefile->ReadBool ( spinning );
}
/*
================
rvWeaponHyperBlaster::PreSave
================
*/
void rvWeaponHyperblaster::PreSave ( void ) {
SetState ( "Idle", 4 );
StopSound( SND_CHANNEL_WEAPON, false );
StopSound( SND_CHANNEL_BODY, false );
StopSound( SND_CHANNEL_ITEM, false );
StopSound( SND_CHANNEL_ANY, false );
}
/*
================
rvWeaponHyperBlaster::PostSave
================
*/
void rvWeaponHyperblaster::PostSave ( void ) {
}
/*
================
rvWeaponHyperblaster::SpinUp
================
*/
void rvWeaponHyperblaster::SpinUp ( void ) {
if ( spinning ) {
return;
}
if ( jointBatteryView != INVALID_JOINT ) {
viewAnimator->SetJointAngularVelocity ( jointBatteryView, idAngles(0,HYPERBLASTER_SPIN_SPEED,0), gameLocal.time, 50 );
}
StopSound ( SND_CHANNEL_BODY2, false );
StartSound ( "snd_battery_spin", SND_CHANNEL_BODY2, 0, false, NULL );
spinning = true;
}
/*
================
rvWeaponHyperblaster::SpinDown
================
*/
void rvWeaponHyperblaster::SpinDown ( void ) {
if ( !spinning ) {
return;
}
StopSound ( SND_CHANNEL_BODY2, false );
StartSound ( "snd_battery_spindown", SND_CHANNEL_BODY2, 0, false, NULL );
if ( jointBatteryView != INVALID_JOINT ) {
viewAnimator->SetJointAngularVelocity ( jointBatteryView, idAngles(0,0,0), gameLocal.time, 500 );
}
spinning = false;
}
/*
===============================================================================
States
===============================================================================
*/
CLASS_STATES_DECLARATION ( rvWeaponHyperblaster )
STATE ( "Idle", rvWeaponHyperblaster::State_Idle)
STATE ( "Fire", rvWeaponHyperblaster::State_Fire )
STATE ( "Reload", rvWeaponHyperblaster::State_Reload )
END_CLASS_STATES
/*
================
rvWeaponHyperblaster::State_Idle
================
*/
stateResult_t rvWeaponHyperblaster::State_Idle( const stateParms_t& parms ) {
enum {
STAGE_INIT,
STAGE_WAIT,
};
switch ( parms.stage ) {
case STAGE_INIT:
if ( !AmmoAvailable ( ) ) {
SetStatus ( WP_OUTOFAMMO );
} else {
SetStatus ( WP_READY );
}
SpinDown ( );
if ( ClipSize() ) {
viewModel->SetShaderParm ( HYPERBLASTER_SPARM_BATTERY, (float)AmmoInClip()/ClipSize() );
} else {
viewModel->SetShaderParm ( HYPERBLASTER_SPARM_BATTERY, 1.0f );
}
PlayCycle( ANIMCHANNEL_ALL, "idle", parms.blendFrames );
return SRESULT_STAGE ( STAGE_WAIT );
case STAGE_WAIT:
if ( wsfl.lowerWeapon ) {
SetState ( "Lower", 4 );
return SRESULT_DONE;
}
if ( !clipSize ) {
if ( gameLocal.time > nextAttackTime && wsfl.attack && AmmoAvailable ( ) ) {
SetState ( "Fire", 0 );
return SRESULT_DONE;
}
} else {
if ( gameLocal.time > nextAttackTime && wsfl.attack && AmmoInClip ( ) ) {
SetState ( "Fire", 0 );
return SRESULT_DONE;
}
if ( wsfl.attack && AutoReload() && !AmmoInClip ( ) && AmmoAvailable () ) {
SetState ( "Reload", 4 );
return SRESULT_DONE;
}
if ( wsfl.netReload || (wsfl.reload && AmmoInClip() < ClipSize() && AmmoAvailable()>AmmoInClip()) ) {
SetState ( "Reload", 4 );
return SRESULT_DONE;
}
}
return SRESULT_WAIT;
}
return SRESULT_ERROR;
}
/*
================
rvWeaponHyperblaster::State_Fire
================
*/
stateResult_t rvWeaponHyperblaster::State_Fire ( const stateParms_t& parms ) {
enum {
STAGE_INIT,
STAGE_WAIT,
};
switch ( parms.stage ) {
case STAGE_INIT:
SpinUp ( );
nextAttackTime = gameLocal.time + (fireRate * owner->PowerUpModifier ( PMOD_FIRERATE ));
Attack ( false, 1, spread, 0, 1.0f );
if ( ClipSize() ) {
viewModel->SetShaderParm ( HYPERBLASTER_SPARM_BATTERY, (float)AmmoInClip()/ClipSize() );
} else {
viewModel->SetShaderParm ( HYPERBLASTER_SPARM_BATTERY, 1.0f );
}
PlayAnim ( ANIMCHANNEL_ALL, "fire", 0 );
return SRESULT_STAGE ( STAGE_WAIT );
case STAGE_WAIT:
if ( wsfl.attack && gameLocal.time >= nextAttackTime && AmmoInClip() && !wsfl.lowerWeapon ) {
SetState ( "Fire", 0 );
return SRESULT_DONE;
}
if ( (!wsfl.attack || !AmmoInClip() || wsfl.lowerWeapon) && AnimDone ( ANIMCHANNEL_ALL, 0 ) ) {
SetState ( "Idle", 0 );
return SRESULT_DONE;
}
return SRESULT_WAIT;
}
return SRESULT_ERROR;
}
/*
================
rvWeaponHyperblaster::State_Reload
================
*/
stateResult_t rvWeaponHyperblaster::State_Reload ( const stateParms_t& parms ) {
enum {
STAGE_INIT,
STAGE_WAIT,
};
switch ( parms.stage ) {
case STAGE_INIT:
if ( wsfl.netReload ) {
wsfl.netReload = false;
} else {
NetReload ( );
}
SpinDown ( );
viewModel->SetShaderParm ( HYPERBLASTER_SPARM_BATTERY, 0 );
SetStatus ( WP_RELOAD );
PlayAnim ( ANIMCHANNEL_ALL, "reload", parms.blendFrames );
return SRESULT_STAGE ( STAGE_WAIT );
case STAGE_WAIT:
if ( AnimDone ( ANIMCHANNEL_ALL, 4 ) ) {
AddToClip ( ClipSize() );
SetState ( "Idle", 4 );
return SRESULT_DONE;
}
if ( wsfl.lowerWeapon ) {
SetState ( "Lower", 4 );
return SRESULT_DONE;
}
return SRESULT_WAIT;
}
return SRESULT_ERROR;
}