1
0
mirror of https://github.com/alliedmodders/hl2sdk.git synced 2025-01-12 11:42:10 +08:00
hl2sdk/game/shared/sdk/weapon_basesdkgrenade.cpp

364 lines
9.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "weapon_sdkbase.h"
#include "gamerules.h"
#include "npcevent.h"
#include "engine/IEngineSound.h"
#include "weapon_basesdkgrenade.h"
#include "in_buttons.h"
#ifdef CLIENT_DLL
#include "c_sdk_player.h"
#else
#include "sdk_player.h"
#include "items.h"
#endif
#define GRENADE_TIMER 1.5f //Seconds
IMPLEMENT_NETWORKCLASS_ALIASED( BaseSDKGrenade, DT_BaseSDKGrenade )
BEGIN_NETWORK_TABLE(CBaseSDKGrenade, DT_BaseSDKGrenade)
#ifndef CLIENT_DLL
SendPropBool( SENDINFO(m_bRedraw) ),
SendPropBool( SENDINFO(m_bPinPulled) ),
SendPropFloat( SENDINFO(m_fThrowTime), 0, SPROP_NOSCALE ),
#else
RecvPropBool( RECVINFO(m_bRedraw) ),
RecvPropBool( RECVINFO(m_bPinPulled) ),
RecvPropFloat( RECVINFO(m_fThrowTime) ),
#endif
END_NETWORK_TABLE()
#ifdef CLIENT_DLL
BEGIN_PREDICTION_DATA( CBaseSDKGrenade )
DEFINE_PRED_FIELD( m_bRedraw, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
DEFINE_PRED_FIELD( m_bRedraw, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
END_PREDICTION_DATA()
#endif
LINK_ENTITY_TO_CLASS( weapon_basesdkgrenade, CBaseSDKGrenade );
CBaseSDKGrenade::CBaseSDKGrenade()
{
m_bRedraw = false;
m_bPinPulled = false;
m_fThrowTime = 0;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseSDKGrenade::Precache()
{
BaseClass::Precache();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CBaseSDKGrenade::Deploy()
{
m_bRedraw = false;
m_bPinPulled = false;
m_fThrowTime = 0;
return BaseClass::Deploy();
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CBaseSDKGrenade::Holster( CBaseCombatWeapon *pSwitchingTo )
{
m_bRedraw = false;
m_bPinPulled = false; // when this is holstered make sure the pin isnt pulled.
m_fThrowTime = 0;
#ifndef CLIENT_DLL
// If they attempt to switch weapons before the throw animation is done,
// allow it, but kill the weapon if we have to.
CSDKPlayer *pPlayer = GetPlayerOwner();
if( pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0 )
{
CBaseCombatCharacter *pOwner = (CBaseCombatCharacter *)pPlayer;
pOwner->Weapon_Drop( this );
UTIL_Remove(this);
}
#endif
return BaseClass::Holster( pSwitchingTo );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseSDKGrenade::PrimaryAttack()
{
if ( m_bRedraw || m_bPinPulled )
return;
CSDKPlayer *pPlayer = GetPlayerOwner();
if ( !pPlayer || pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 )
return;
// The pull pin animation has to finish, then we wait until they aren't holding the primary
// attack button, then throw the grenade.
SendWeaponAnim( ACT_VM_PULLPIN );
m_bPinPulled = true;
// Don't let weapon idle interfere in the middle of a throw!
SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() );
m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseSDKGrenade::SecondaryAttack()
{
if ( m_bRedraw )
return;
CSDKPlayer *pPlayer = GetPlayerOwner();
if ( pPlayer == NULL )
return;
//See if we're ducking
if ( pPlayer->GetFlags() & FL_DUCKING )
{
//Send the weapon animation
SendWeaponAnim( ACT_VM_SECONDARYATTACK );
}
else
{
//Send the weapon animation
SendWeaponAnim( ACT_VM_HAULBACK );
}
// Don't let weapon idle interfere in the middle of a throw!
SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() );
m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration();
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CBaseSDKGrenade::Reload()
{
if ( ( m_bRedraw ) && ( m_flNextPrimaryAttack <= gpGlobals->curtime ) && ( m_flNextSecondaryAttack <= gpGlobals->curtime ) )
{
//Redraw the weapon
SendWeaponAnim( ACT_VM_DRAW );
//Update our times
m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration();
SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() );
}
return true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CBaseSDKGrenade::ItemPostFrame()
{
CSDKPlayer *pPlayer = GetPlayerOwner();
if ( !pPlayer )
return;
CBaseViewModel *vm = pPlayer->GetViewModel( m_nViewModelIndex );
if ( !vm )
return;
// If they let go of the fire button, they want to throw the grenade.
if ( m_bPinPulled && !(pPlayer->m_nButtons & IN_ATTACK) )
{
pPlayer->DoAnimationEvent( PLAYERANIMEVENT_THROW_GRENADE );
StartGrenadeThrow();
DecrementAmmo( pPlayer );
m_bPinPulled = false;
SendWeaponAnim( ACT_VM_THROW );
SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() );
}
else if ((m_fThrowTime > 0) && (m_fThrowTime < gpGlobals->curtime))
{
ThrowGrenade();
}
else if( m_bRedraw )
{
// Has the throw animation finished playing
if( m_flTimeWeaponIdle < gpGlobals->curtime )
{
#ifdef GAME_DLL
// if we're officially out of grenades, ditch this weapon
if( pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0 )
{
pPlayer->Weapon_Drop( this, NULL, NULL );
UTIL_Remove(this);
}
else
{
pPlayer->SwitchToNextBestWeapon( this );
}
#endif
return; //don't animate this grenade any more!
}
}
else if( !m_bRedraw )
{
BaseClass::ItemPostFrame();
}
}
#ifdef CLIENT_DLL
void CBaseSDKGrenade::DecrementAmmo( CBaseCombatCharacter *pOwner )
{
}
void CBaseSDKGrenade::DropGrenade()
{
m_bRedraw = true;
m_fThrowTime = 0.0f;
}
void CBaseSDKGrenade::ThrowGrenade()
{
m_bRedraw = true;
m_fThrowTime = 0.0f;
}
void CBaseSDKGrenade::StartGrenadeThrow()
{
m_fThrowTime = gpGlobals->curtime + 0.1f;
}
#else
BEGIN_DATADESC( CBaseSDKGrenade )
DEFINE_FIELD( m_bRedraw, FIELD_BOOLEAN ),
END_DATADESC()
int CBaseSDKGrenade::CapabilitiesGet()
{
return bits_CAP_WEAPON_RANGE_ATTACK1;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pOwner -
//-----------------------------------------------------------------------------
void CBaseSDKGrenade::DecrementAmmo( CBaseCombatCharacter *pOwner )
{
pOwner->RemoveAmmo( 1, m_iPrimaryAmmoType );
}
void CBaseSDKGrenade::StartGrenadeThrow()
{
m_fThrowTime = gpGlobals->curtime + 0.1f;
}
void CBaseSDKGrenade::ThrowGrenade()
{
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
if ( !pPlayer )
{
Assert( false );
return;
}
QAngle angThrow = pPlayer->LocalEyeAngles();
Vector vForward, vRight, vUp;
if (angThrow.x < 90 )
angThrow.x = -10 + angThrow.x * ((90 + 10) / 90.0);
else
{
angThrow.x = 360.0f - angThrow.x;
angThrow.x = -10 + angThrow.x * -((90 - 10) / 90.0);
}
float flVel = (90 - angThrow.x) * 6;
if (flVel > 750)
flVel = 750;
AngleVectors( angThrow, &vForward, &vRight, &vUp );
Vector vecSrc = pPlayer->GetAbsOrigin() + pPlayer->GetViewOffset();
vecSrc += vForward * 16;
Vector vecThrow = vForward * flVel + pPlayer->GetAbsVelocity();
EmitGrenade( vecSrc, vec3_angle, vecThrow, AngularImpulse(600,random->RandomInt(-1200,1200),0), pPlayer );
m_bRedraw = true;
m_fThrowTime = 0.0f;
}
void CBaseSDKGrenade::DropGrenade()
{
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
if ( !pPlayer )
{
Assert( false );
return;
}
Vector vForward;
pPlayer->EyeVectors( &vForward );
Vector vecSrc = pPlayer->GetAbsOrigin() + pPlayer->GetViewOffset() + vForward * 16;
Vector vecVel = pPlayer->GetAbsVelocity();
EmitGrenade( vecSrc, vec3_angle, vecVel, AngularImpulse(600,random->RandomInt(-1200,1200),0), pPlayer );
m_bRedraw = true;
m_fThrowTime = 0.0f;
}
void CBaseSDKGrenade::EmitGrenade( Vector vecSrc, QAngle vecAngles, Vector vecVel, AngularImpulse angImpulse, CBasePlayer *pPlayer )
{
Assert( 0 && "CBaseSDKGrenade::EmitGrenade should not be called. Make sure to implement this in your subclass!\n" );
}
bool CBaseSDKGrenade::AllowsAutoSwitchFrom( void ) const
{
return !m_bPinPulled;
}
#endif