488 lines
11 KiB
C++
488 lines
11 KiB
C++
|
#include "../../idlib/precompiled.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include "../Game_local.h"
|
||
|
#include "../Weapon.h"
|
||
|
|
||
|
#define BLASTER_SPARM_CHARGEGLOW 6
|
||
|
|
||
|
class rvWeaponBlaster : public rvWeapon {
|
||
|
public:
|
||
|
|
||
|
CLASS_PROTOTYPE( rvWeaponBlaster );
|
||
|
|
||
|
rvWeaponBlaster ( void );
|
||
|
|
||
|
virtual void Spawn ( void );
|
||
|
void Save ( idSaveGame *savefile ) const;
|
||
|
void Restore ( idRestoreGame *savefile );
|
||
|
void PreSave ( void );
|
||
|
void PostSave ( void );
|
||
|
|
||
|
protected:
|
||
|
|
||
|
bool UpdateAttack ( void );
|
||
|
bool UpdateFlashlight ( void );
|
||
|
void Flashlight ( bool on );
|
||
|
|
||
|
private:
|
||
|
|
||
|
int chargeTime;
|
||
|
int chargeDelay;
|
||
|
idVec2 chargeGlow;
|
||
|
bool fireForced;
|
||
|
int fireHeldTime;
|
||
|
|
||
|
stateResult_t State_Raise ( const stateParms_t& parms );
|
||
|
stateResult_t State_Lower ( const stateParms_t& parms );
|
||
|
stateResult_t State_Idle ( const stateParms_t& parms );
|
||
|
stateResult_t State_Charge ( const stateParms_t& parms );
|
||
|
stateResult_t State_Charged ( const stateParms_t& parms );
|
||
|
stateResult_t State_Fire ( const stateParms_t& parms );
|
||
|
stateResult_t State_Flashlight ( const stateParms_t& parms );
|
||
|
|
||
|
CLASS_STATES_PROTOTYPE ( rvWeaponBlaster );
|
||
|
};
|
||
|
|
||
|
CLASS_DECLARATION( rvWeapon, rvWeaponBlaster )
|
||
|
END_CLASS
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvWeaponBlaster::rvWeaponBlaster
|
||
|
================
|
||
|
*/
|
||
|
rvWeaponBlaster::rvWeaponBlaster ( void ) {
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvWeaponBlaster::UpdateFlashlight
|
||
|
================
|
||
|
*/
|
||
|
bool rvWeaponBlaster::UpdateFlashlight ( void ) {
|
||
|
if ( !wsfl.flashlight ) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
SetState ( "Flashlight", 0 );
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvWeaponBlaster::Flashlight
|
||
|
================
|
||
|
*/
|
||
|
void rvWeaponBlaster::Flashlight ( bool on ) {
|
||
|
owner->Flashlight ( on );
|
||
|
|
||
|
if ( on ) {
|
||
|
worldModel->ShowSurface ( "models/weapons/blaster/flare" );
|
||
|
viewModel->ShowSurface ( "models/weapons/blaster/flare" );
|
||
|
} else {
|
||
|
worldModel->HideSurface ( "models/weapons/blaster/flare" );
|
||
|
viewModel->HideSurface ( "models/weapons/blaster/flare" );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvWeaponBlaster::UpdateAttack
|
||
|
================
|
||
|
*/
|
||
|
bool rvWeaponBlaster::UpdateAttack ( void ) {
|
||
|
// Clear fire forced
|
||
|
if ( fireForced ) {
|
||
|
if ( !wsfl.attack ) {
|
||
|
fireForced = false;
|
||
|
} else {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// If the player is pressing the fire button and they have enough ammo for a shot
|
||
|
// then start the shooting process.
|
||
|
if ( wsfl.attack && gameLocal.time >= nextAttackTime ) {
|
||
|
// Save the time which the fire button was pressed
|
||
|
if ( fireHeldTime == 0 ) {
|
||
|
nextAttackTime = gameLocal.time + (fireRate * owner->PowerUpModifier ( PMOD_FIRERATE ));
|
||
|
fireHeldTime = gameLocal.time;
|
||
|
viewModel->SetShaderParm ( BLASTER_SPARM_CHARGEGLOW, chargeGlow[0] );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// If they have the charge mod and they have overcome the initial charge
|
||
|
// delay then transition to the charge state.
|
||
|
if ( fireHeldTime != 0 ) {
|
||
|
if ( gameLocal.time - fireHeldTime > chargeDelay ) {
|
||
|
SetState ( "Charge", 4 );
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// If the fire button was let go but was pressed at one point then
|
||
|
// release the shot.
|
||
|
if ( !wsfl.attack ) {
|
||
|
idPlayer * player = gameLocal.GetLocalPlayer();
|
||
|
if( player ) {
|
||
|
|
||
|
if( player->GuiActive()) {
|
||
|
//make sure the player isn't looking at a gui first
|
||
|
SetState ( "Lower", 0 );
|
||
|
} else {
|
||
|
SetState ( "Fire", 0 );
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvWeaponBlaster::Spawn
|
||
|
================
|
||
|
*/
|
||
|
void rvWeaponBlaster::Spawn ( void ) {
|
||
|
viewModel->SetShaderParm ( BLASTER_SPARM_CHARGEGLOW, 0 );
|
||
|
SetState ( "Raise", 0 );
|
||
|
|
||
|
chargeGlow = spawnArgs.GetVec2 ( "chargeGlow" );
|
||
|
chargeTime = SEC2MS ( spawnArgs.GetFloat ( "chargeTime" ) );
|
||
|
chargeDelay = SEC2MS ( spawnArgs.GetFloat ( "chargeDelay" ) );
|
||
|
|
||
|
fireHeldTime = 0;
|
||
|
fireForced = false;
|
||
|
|
||
|
Flashlight ( owner->IsFlashlightOn() );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvWeaponBlaster::Save
|
||
|
================
|
||
|
*/
|
||
|
void rvWeaponBlaster::Save ( idSaveGame *savefile ) const {
|
||
|
savefile->WriteInt ( chargeTime );
|
||
|
savefile->WriteInt ( chargeDelay );
|
||
|
savefile->WriteVec2 ( chargeGlow );
|
||
|
savefile->WriteBool ( fireForced );
|
||
|
savefile->WriteInt ( fireHeldTime );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvWeaponBlaster::Restore
|
||
|
================
|
||
|
*/
|
||
|
void rvWeaponBlaster::Restore ( idRestoreGame *savefile ) {
|
||
|
savefile->ReadInt ( chargeTime );
|
||
|
savefile->ReadInt ( chargeDelay );
|
||
|
savefile->ReadVec2 ( chargeGlow );
|
||
|
savefile->ReadBool ( fireForced );
|
||
|
savefile->ReadInt ( fireHeldTime );
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvWeaponBlaster::PreSave
|
||
|
================
|
||
|
*/
|
||
|
void rvWeaponBlaster::PreSave ( void ) {
|
||
|
|
||
|
SetState ( "Idle", 4 );
|
||
|
|
||
|
StopSound( SND_CHANNEL_WEAPON, 0);
|
||
|
StopSound( SND_CHANNEL_BODY, 0);
|
||
|
StopSound( SND_CHANNEL_ITEM, 0);
|
||
|
StopSound( SND_CHANNEL_ANY, false );
|
||
|
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvWeaponBlaster::PostSave
|
||
|
================
|
||
|
*/
|
||
|
void rvWeaponBlaster::PostSave ( void ) {
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
===============================================================================
|
||
|
|
||
|
States
|
||
|
|
||
|
===============================================================================
|
||
|
*/
|
||
|
|
||
|
CLASS_STATES_DECLARATION ( rvWeaponBlaster )
|
||
|
STATE ( "Raise", rvWeaponBlaster::State_Raise )
|
||
|
STATE ( "Lower", rvWeaponBlaster::State_Lower )
|
||
|
STATE ( "Idle", rvWeaponBlaster::State_Idle)
|
||
|
STATE ( "Charge", rvWeaponBlaster::State_Charge )
|
||
|
STATE ( "Charged", rvWeaponBlaster::State_Charged )
|
||
|
STATE ( "Fire", rvWeaponBlaster::State_Fire )
|
||
|
STATE ( "Flashlight", rvWeaponBlaster::State_Flashlight )
|
||
|
END_CLASS_STATES
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvWeaponBlaster::State_Raise
|
||
|
================
|
||
|
*/
|
||
|
stateResult_t rvWeaponBlaster::State_Raise( const stateParms_t& parms ) {
|
||
|
enum {
|
||
|
RAISE_INIT,
|
||
|
RAISE_WAIT,
|
||
|
};
|
||
|
switch ( parms.stage ) {
|
||
|
case RAISE_INIT:
|
||
|
SetStatus ( WP_RISING );
|
||
|
PlayAnim( ANIMCHANNEL_ALL, "raise", parms.blendFrames );
|
||
|
return SRESULT_STAGE(RAISE_WAIT);
|
||
|
|
||
|
case RAISE_WAIT:
|
||
|
if ( AnimDone ( ANIMCHANNEL_ALL, 4 ) ) {
|
||
|
SetState ( "Idle", 4 );
|
||
|
return SRESULT_DONE;
|
||
|
}
|
||
|
if ( wsfl.lowerWeapon ) {
|
||
|
SetState ( "Lower", 4 );
|
||
|
return SRESULT_DONE;
|
||
|
}
|
||
|
return SRESULT_WAIT;
|
||
|
}
|
||
|
return SRESULT_ERROR;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvWeaponBlaster::State_Lower
|
||
|
================
|
||
|
*/
|
||
|
stateResult_t rvWeaponBlaster::State_Lower ( const stateParms_t& parms ) {
|
||
|
enum {
|
||
|
LOWER_INIT,
|
||
|
LOWER_WAIT,
|
||
|
LOWER_WAITRAISE
|
||
|
};
|
||
|
switch ( parms.stage ) {
|
||
|
case LOWER_INIT:
|
||
|
SetStatus ( WP_LOWERING );
|
||
|
PlayAnim( ANIMCHANNEL_ALL, "putaway", parms.blendFrames );
|
||
|
return SRESULT_STAGE(LOWER_WAIT);
|
||
|
|
||
|
case LOWER_WAIT:
|
||
|
if ( AnimDone ( ANIMCHANNEL_ALL, 0 ) ) {
|
||
|
SetStatus ( WP_HOLSTERED );
|
||
|
return SRESULT_STAGE(LOWER_WAITRAISE);
|
||
|
}
|
||
|
return SRESULT_WAIT;
|
||
|
|
||
|
case LOWER_WAITRAISE:
|
||
|
if ( wsfl.raiseWeapon ) {
|
||
|
SetState ( "Raise", 0 );
|
||
|
return SRESULT_DONE;
|
||
|
}
|
||
|
return SRESULT_WAIT;
|
||
|
}
|
||
|
return SRESULT_ERROR;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvWeaponBlaster::State_Idle
|
||
|
================
|
||
|
*/
|
||
|
stateResult_t rvWeaponBlaster::State_Idle ( const stateParms_t& parms ) {
|
||
|
enum {
|
||
|
IDLE_INIT,
|
||
|
IDLE_WAIT,
|
||
|
};
|
||
|
switch ( parms.stage ) {
|
||
|
case IDLE_INIT:
|
||
|
SetStatus ( WP_READY );
|
||
|
PlayCycle( ANIMCHANNEL_ALL, "idle", parms.blendFrames );
|
||
|
return SRESULT_STAGE ( IDLE_WAIT );
|
||
|
|
||
|
case IDLE_WAIT:
|
||
|
if ( wsfl.lowerWeapon ) {
|
||
|
SetState ( "Lower", 4 );
|
||
|
return SRESULT_DONE;
|
||
|
}
|
||
|
|
||
|
if ( UpdateFlashlight ( ) ) {
|
||
|
return SRESULT_DONE;
|
||
|
}
|
||
|
if ( UpdateAttack ( ) ) {
|
||
|
return SRESULT_DONE;
|
||
|
}
|
||
|
return SRESULT_WAIT;
|
||
|
}
|
||
|
return SRESULT_ERROR;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvWeaponBlaster::State_Charge
|
||
|
================
|
||
|
*/
|
||
|
stateResult_t rvWeaponBlaster::State_Charge ( const stateParms_t& parms ) {
|
||
|
enum {
|
||
|
CHARGE_INIT,
|
||
|
CHARGE_WAIT,
|
||
|
};
|
||
|
switch ( parms.stage ) {
|
||
|
case CHARGE_INIT:
|
||
|
viewModel->SetShaderParm ( BLASTER_SPARM_CHARGEGLOW, chargeGlow[0] );
|
||
|
StartSound ( "snd_charge", SND_CHANNEL_ITEM, 0, false, NULL );
|
||
|
PlayCycle( ANIMCHANNEL_ALL, "charging", parms.blendFrames );
|
||
|
return SRESULT_STAGE ( CHARGE_WAIT );
|
||
|
|
||
|
case CHARGE_WAIT:
|
||
|
if ( gameLocal.time - fireHeldTime < chargeTime ) {
|
||
|
float f;
|
||
|
f = (float)(gameLocal.time - fireHeldTime) / (float)chargeTime;
|
||
|
f = chargeGlow[0] + f * (chargeGlow[1] - chargeGlow[0]);
|
||
|
f = idMath::ClampFloat ( chargeGlow[0], chargeGlow[1], f );
|
||
|
viewModel->SetShaderParm ( BLASTER_SPARM_CHARGEGLOW, f );
|
||
|
|
||
|
if ( !wsfl.attack ) {
|
||
|
SetState ( "Fire", 0 );
|
||
|
return SRESULT_DONE;
|
||
|
}
|
||
|
|
||
|
return SRESULT_WAIT;
|
||
|
}
|
||
|
SetState ( "Charged", 4 );
|
||
|
return SRESULT_DONE;
|
||
|
}
|
||
|
return SRESULT_ERROR;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvWeaponBlaster::State_Charged
|
||
|
================
|
||
|
*/
|
||
|
stateResult_t rvWeaponBlaster::State_Charged ( const stateParms_t& parms ) {
|
||
|
enum {
|
||
|
CHARGED_INIT,
|
||
|
CHARGED_WAIT,
|
||
|
};
|
||
|
switch ( parms.stage ) {
|
||
|
case CHARGED_INIT:
|
||
|
viewModel->SetShaderParm ( BLASTER_SPARM_CHARGEGLOW, 1.0f );
|
||
|
|
||
|
StopSound ( SND_CHANNEL_ITEM, false );
|
||
|
StartSound ( "snd_charge_loop", SND_CHANNEL_ITEM, 0, false, NULL );
|
||
|
StartSound ( "snd_charge_click", SND_CHANNEL_BODY, 0, false, NULL );
|
||
|
return SRESULT_STAGE(CHARGED_WAIT);
|
||
|
|
||
|
case CHARGED_WAIT:
|
||
|
if ( !wsfl.attack ) {
|
||
|
fireForced = true;
|
||
|
SetState ( "Fire", 0 );
|
||
|
return SRESULT_DONE;
|
||
|
}
|
||
|
return SRESULT_WAIT;
|
||
|
}
|
||
|
return SRESULT_ERROR;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvWeaponBlaster::State_Fire
|
||
|
================
|
||
|
*/
|
||
|
stateResult_t rvWeaponBlaster::State_Fire ( const stateParms_t& parms ) {
|
||
|
enum {
|
||
|
FIRE_INIT,
|
||
|
FIRE_WAIT,
|
||
|
};
|
||
|
switch ( parms.stage ) {
|
||
|
case FIRE_INIT:
|
||
|
|
||
|
StopSound ( SND_CHANNEL_ITEM, false );
|
||
|
viewModel->SetShaderParm ( BLASTER_SPARM_CHARGEGLOW, 0 );
|
||
|
//don't fire if we're targeting a gui.
|
||
|
idPlayer* player;
|
||
|
player = gameLocal.GetLocalPlayer();
|
||
|
|
||
|
//make sure the player isn't looking at a gui first
|
||
|
if( player && player->GuiActive() ) {
|
||
|
fireHeldTime = 0;
|
||
|
SetState ( "Lower", 0 );
|
||
|
return SRESULT_DONE;
|
||
|
}
|
||
|
|
||
|
if( player && !player->CanFire() ) {
|
||
|
fireHeldTime = 0;
|
||
|
SetState ( "Idle", 4 );
|
||
|
return SRESULT_DONE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
if ( gameLocal.time - fireHeldTime > chargeTime ) {
|
||
|
Attack ( true, 1, spread, 0, 1.0f );
|
||
|
PlayEffect ( "fx_chargedflash", barrelJointView, false );
|
||
|
PlayAnim( ANIMCHANNEL_ALL, "chargedfire", parms.blendFrames );
|
||
|
} else {
|
||
|
Attack ( false, 1, spread, 0, 1.0f );
|
||
|
PlayEffect ( "fx_normalflash", barrelJointView, false );
|
||
|
PlayAnim( ANIMCHANNEL_ALL, "fire", parms.blendFrames );
|
||
|
}
|
||
|
fireHeldTime = 0;
|
||
|
|
||
|
return SRESULT_STAGE(FIRE_WAIT);
|
||
|
|
||
|
case FIRE_WAIT:
|
||
|
if ( AnimDone ( ANIMCHANNEL_ALL, 4 ) ) {
|
||
|
SetState ( "Idle", 4 );
|
||
|
return SRESULT_DONE;
|
||
|
}
|
||
|
if ( UpdateFlashlight ( ) || UpdateAttack ( ) ) {
|
||
|
return SRESULT_DONE;
|
||
|
}
|
||
|
return SRESULT_WAIT;
|
||
|
}
|
||
|
return SRESULT_ERROR;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
================
|
||
|
rvWeaponBlaster::State_Flashlight
|
||
|
================
|
||
|
*/
|
||
|
stateResult_t rvWeaponBlaster::State_Flashlight ( const stateParms_t& parms ) {
|
||
|
enum {
|
||
|
FLASHLIGHT_INIT,
|
||
|
FLASHLIGHT_WAIT,
|
||
|
};
|
||
|
switch ( parms.stage ) {
|
||
|
case FLASHLIGHT_INIT:
|
||
|
SetStatus ( WP_FLASHLIGHT );
|
||
|
// Wait for the flashlight anim to play
|
||
|
PlayAnim( ANIMCHANNEL_ALL, "flashlight", 0 );
|
||
|
return SRESULT_STAGE ( FLASHLIGHT_WAIT );
|
||
|
|
||
|
case FLASHLIGHT_WAIT:
|
||
|
if ( !AnimDone ( ANIMCHANNEL_ALL, 4 ) ) {
|
||
|
return SRESULT_WAIT;
|
||
|
}
|
||
|
|
||
|
if ( owner->IsFlashlightOn() ) {
|
||
|
Flashlight ( false );
|
||
|
} else {
|
||
|
Flashlight ( true );
|
||
|
}
|
||
|
|
||
|
SetState ( "Idle", 4 );
|
||
|
return SRESULT_DONE;
|
||
|
}
|
||
|
return SRESULT_ERROR;
|
||
|
}
|