mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-08 01:39:36 +00:00
1
This commit is contained in:
@@ -0,0 +1,377 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: TF Base Grenade.
|
||||
//
|
||||
//=============================================================================//
|
||||
#include "cbase.h"
|
||||
#include "tf_weaponbase.h"
|
||||
#include "tf_weaponbase_grenade.h"
|
||||
#include "tf_gamerules.h"
|
||||
#include "npcevent.h"
|
||||
#include "engine/IEngineSound.h"
|
||||
#include "in_buttons.h"
|
||||
#include "tf_weaponbase_grenadeproj.h"
|
||||
#include "eventlist.h"
|
||||
|
||||
// Client specific.
|
||||
#ifdef CLIENT_DLL
|
||||
#include "c_tf_player.h"
|
||||
// Server specific.
|
||||
#else
|
||||
#include "tf_player.h"
|
||||
#include "items.h"
|
||||
#endif
|
||||
|
||||
#define GRENADE_TIMER 1.5f // seconds
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// TF Grenade tables.
|
||||
//
|
||||
|
||||
IMPLEMENT_NETWORKCLASS_ALIASED( TFWeaponBaseGrenade, DT_TFWeaponBaseGrenade )
|
||||
|
||||
BEGIN_NETWORK_TABLE( CTFWeaponBaseGrenade, DT_TFWeaponBaseGrenade )
|
||||
// Client specific.
|
||||
#ifdef CLIENT_DLL
|
||||
RecvPropBool( RECVINFO( m_bPrimed ) ),
|
||||
RecvPropFloat( RECVINFO( m_flThrowTime ) ),
|
||||
RecvPropBool( RECVINFO( m_bThrow ) ),
|
||||
// Server specific.
|
||||
#else
|
||||
SendPropBool( SENDINFO( m_bPrimed ) ),
|
||||
SendPropTime( SENDINFO( m_flThrowTime ) ),
|
||||
SendPropBool( SENDINFO( m_bThrow ) ),
|
||||
#endif
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
BEGIN_PREDICTION_DATA( CTFWeaponBaseGrenade )
|
||||
#ifdef CLIENT_DLL
|
||||
DEFINE_PRED_FIELD( m_bPrimed, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
|
||||
DEFINE_PRED_FIELD( m_flThrowTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
|
||||
DEFINE_PRED_FIELD( m_bThrow, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
|
||||
#endif
|
||||
END_PREDICTION_DATA()
|
||||
|
||||
LINK_ENTITY_TO_CLASS( tf_weaponbase_grenade, CTFWeaponBaseGrenade );
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// TF Grenade functions.
|
||||
//
|
||||
|
||||
CTFWeaponBaseGrenade::CTFWeaponBaseGrenade()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructor.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFWeaponBaseGrenade::Spawn( void )
|
||||
{
|
||||
BaseClass::Spawn();
|
||||
|
||||
SetViewModelIndex( 1 );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFWeaponBaseGrenade::Precache()
|
||||
{
|
||||
BaseClass::Precache();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CTFWeaponBaseGrenade::IsPrimed( void )
|
||||
{
|
||||
return m_bPrimed;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CTFWeaponBaseGrenade::Deploy( void )
|
||||
{
|
||||
if ( BaseClass::Deploy() )
|
||||
{
|
||||
Prime();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFWeaponBaseGrenade::Prime()
|
||||
{
|
||||
CTFWeaponInfo weaponInfo = GetTFWpnData();
|
||||
m_flThrowTime = gpGlobals->curtime + weaponInfo.m_flPrimerTime;
|
||||
m_bPrimed = true;
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
if ( GetWeaponID() != TF_WEAPON_GRENADE_SMOKE_BOMB )
|
||||
{
|
||||
// Get the player owning the weapon.
|
||||
CTFPlayer *pPlayer = ToTFPlayer( GetPlayerOwner() );
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
pPlayer->RemoveInvisibility();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFWeaponBaseGrenade::Throw()
|
||||
{
|
||||
if ( !m_bPrimed )
|
||||
return;
|
||||
|
||||
m_bPrimed = false;
|
||||
m_bThrow = false;
|
||||
|
||||
// Get the owning player.
|
||||
CTFPlayer *pPlayer = ToTFPlayer( GetOwner() );
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
#ifdef GAME_DLL
|
||||
// Calculate the time remaining.
|
||||
float flTime = m_flThrowTime - gpGlobals->curtime;
|
||||
bool bExplodingInHand = ( flTime <= 0.0f );
|
||||
|
||||
// Players who are dying may not have their death state set, so check that too
|
||||
bool bExplodingOnDeath = ( !pPlayer->IsAlive() || pPlayer->StateGet() == TF_STATE_DYING );
|
||||
|
||||
Vector vecSrc, vecThrow;
|
||||
vecSrc = pPlayer->Weapon_ShootPosition();
|
||||
|
||||
if ( bExplodingInHand || bExplodingOnDeath )
|
||||
{
|
||||
vecThrow = vec3_origin;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Determine the throw angle and velocity.
|
||||
QAngle angThrow = pPlayer->LocalEyeAngles();
|
||||
if ( angThrow.x < 90.0f )
|
||||
{
|
||||
angThrow.x = -10.0f + angThrow.x * ( ( 90.0f + 10.0f ) / 90.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
angThrow.x = 360.0f - angThrow.x;
|
||||
angThrow.x = -10.0f + angThrow.x * -( ( 90.0f - 10.0f ) / 90.0f );
|
||||
}
|
||||
|
||||
// Adjust for the lowering of the spawn point
|
||||
angThrow.x -= 10;
|
||||
|
||||
float flVelocity = ( 90.0f - angThrow.x ) * 8.0f;
|
||||
if ( flVelocity > 950.0f )
|
||||
{
|
||||
flVelocity = 950.0f;
|
||||
}
|
||||
|
||||
Vector vForward, vRight, vUp;
|
||||
AngleVectors( angThrow, &vForward, &vRight, &vUp );
|
||||
|
||||
// Throw from the player's left hand position.
|
||||
vecSrc += vForward * 16.0f + vRight * -8.0f + vUp * -20.0f;
|
||||
|
||||
vecThrow = vForward * flVelocity;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Debug!!!
|
||||
char str[256];
|
||||
Q_snprintf( str, sizeof( str ),"GrenadeTime = %f\n", flTime );
|
||||
NDebugOverlay::ScreenText( 0.5f, 0.38f, str, 255, 255, 255, 255, 2.0f );
|
||||
#endif
|
||||
|
||||
QAngle vecAngles = RandomAngle( 0, 360 );
|
||||
|
||||
// Create the projectile and send in the time remaining.
|
||||
if ( !bExplodingInHand )
|
||||
{
|
||||
EmitGrenade( vecSrc, vecAngles, vecThrow, AngularImpulse( 600, random->RandomInt( -1200, 1200 ), 0 ), pPlayer, flTime );
|
||||
}
|
||||
else
|
||||
{
|
||||
// We're holding onto an exploding grenade
|
||||
CTFWeaponBaseGrenadeProj *pGrenade = EmitGrenade( vecSrc, vecAngles, vecThrow, AngularImpulse( 600, random->RandomInt( -1200, 1200 ), 0 ), pPlayer, 0.0 );
|
||||
if ( pGrenade )
|
||||
{
|
||||
pGrenade->Detonate();
|
||||
}
|
||||
}
|
||||
|
||||
// The grenade is about to be destroyed, so it won't be able to holster.
|
||||
// Handle the viewmodel hiding for it.
|
||||
if ( bExplodingInHand || bExplodingOnDeath )
|
||||
{
|
||||
SendWeaponAnim( ACT_VM_IDLE );
|
||||
CBaseViewModel *vm = pPlayer->GetViewModel( 1 );
|
||||
if ( vm )
|
||||
{
|
||||
vm->AddEffects( EF_NODRAW );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Reset the throw time
|
||||
m_flThrowTime = 0.0f;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CTFWeaponBaseGrenade::ShouldDetonate( void )
|
||||
{
|
||||
return ( m_flThrowTime != 0.0f ) && ( m_flThrowTime < gpGlobals->curtime );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFWeaponBaseGrenade::ItemPostFrame()
|
||||
{
|
||||
CTFPlayer *pPlayer = ToTFPlayer( GetPlayerOwner() );
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
if ( m_bPrimed )
|
||||
{
|
||||
// Is our timer up? If so, blow up immediately
|
||||
if ( ShouldDetonate() )
|
||||
{
|
||||
Throw();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !m_bThrow && !( pPlayer->m_nButtons & IN_GRENADE1 || pPlayer->m_nButtons & IN_GRENADE2 ) )
|
||||
{
|
||||
// Start throwing
|
||||
pPlayer->DoAnimationEvent( PLAYERANIMEVENT_ATTACK_GRENADE );
|
||||
m_bThrow = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_bThrow )
|
||||
{
|
||||
if ( GetActivity() != ACT_VM_PRIMARYATTACK )
|
||||
{
|
||||
// Start the throw animation
|
||||
if ( !SendWeaponAnim( ACT_VM_PRIMARYATTACK ) )
|
||||
{
|
||||
Throw();
|
||||
}
|
||||
}
|
||||
else if ( HasWeaponIdleTimeElapsed() )
|
||||
{
|
||||
// The Throw call here exists solely to catch the lone case of thirdperson where the
|
||||
// viewmodel isn't being drawn, and hence the anim event doesn't trigger and force a throw.
|
||||
// In all other cases, it'll do nothing because the grenade has already been thrown.
|
||||
Throw();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !m_bPrimed && !m_bThrow )
|
||||
{
|
||||
// Once we've finished being holstered, we'll be hidden. When that happens,
|
||||
// tell our player that we're all done with the grenade throw.
|
||||
if ( IsEffectActive(EF_NODRAW) )
|
||||
{
|
||||
pPlayer->FinishThrowGrenade();
|
||||
return;
|
||||
}
|
||||
|
||||
// We've been thrown. Go away.
|
||||
if ( HasWeaponIdleTimeElapsed() )
|
||||
{
|
||||
Holster();
|
||||
}
|
||||
}
|
||||
|
||||
// Go straight to idle anim when deploy is done
|
||||
if ( m_flTimeWeaponIdle <= gpGlobals->curtime )
|
||||
{
|
||||
SendWeaponAnim( ACT_VM_IDLE );
|
||||
}
|
||||
}
|
||||
|
||||
bool CTFWeaponBaseGrenade::ShouldLowerMainWeapon( void )
|
||||
{
|
||||
return GetTFWpnData().m_bLowerWeapon;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Client specific functions.
|
||||
//
|
||||
#ifdef CLIENT_DLL
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CTFWeaponBaseGrenade::ShouldDraw( void )
|
||||
{
|
||||
if ( !BaseClass::ShouldDraw() )
|
||||
{
|
||||
// Grenades need to be visible whenever they're being primed & thrown
|
||||
if ( !m_bPrimed )
|
||||
return false;
|
||||
|
||||
// Don't draw primed grenades for local player in first person players
|
||||
if ( !(ToPlayer(GetOwner())->ShouldDrawThisPlayer()) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Server specific functions.
|
||||
//
|
||||
#else
|
||||
|
||||
BEGIN_DATADESC( CTFWeaponBaseGrenade )
|
||||
END_DATADESC()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFWeaponBaseGrenade::HandleAnimEvent( animevent_t *pEvent )
|
||||
{
|
||||
if ( (pEvent->type & AE_TYPE_NEWEVENTSYSTEM) )
|
||||
{
|
||||
if ( pEvent->event == AE_WPN_PRIMARYATTACK )
|
||||
{
|
||||
Throw();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
BaseClass::HandleAnimEvent( pEvent );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CTFWeaponBaseGrenadeProj *CTFWeaponBaseGrenade::EmitGrenade( Vector vecSrc, QAngle vecAngles, Vector vecVel, AngularImpulse angImpulse, CBasePlayer *pPlayer, float flTime, int iFlags )
|
||||
{
|
||||
Assert( 0 && "CBaseCSGrenade::EmitGrenade should not be called. Make sure to implement this in your subclass!\n" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user