You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
368 lines
11 KiB
368 lines
11 KiB
![]()
4 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// $NoKeywords: $
|
||
|
//=============================================================================//
|
||
|
#include "cbase.h"
|
||
|
#include "tf_player.h"
|
||
|
#include "tf_basecombatweapon.h"
|
||
|
#include "tf_defines.h"
|
||
|
#include "in_buttons.h"
|
||
|
#include "gamerules.h"
|
||
|
#include "ammodef.h"
|
||
|
#include "tf_obj.h"
|
||
|
#include "weapon_mortar.h"
|
||
|
#include "smoke_trail.h"
|
||
|
#include "tf_shareddefs.h"
|
||
|
#include "tf_team.h"
|
||
|
#include "tf_gamerules.h"
|
||
|
#include "tf_obj_antimortar.h"
|
||
|
#include "vstdlib/random.h"
|
||
|
#include "engine/IEngineSound.h"
|
||
|
|
||
|
extern short g_sModelIndexFireball;
|
||
|
|
||
|
// Damage CVars
|
||
|
ConVar weapon_mortar_shell_damage( "weapon_mortar_shell_damage","0", FCVAR_NONE, "Mortar's standard shell maximum damage" );
|
||
|
ConVar weapon_mortar_shell_radius( "weapon_mortar_shell_radius","0", FCVAR_NONE, "Mortar's standard shell splash radius" );
|
||
|
ConVar weapon_mortar_starburst_damage( "weapon_mortar_starburst_damage","0", FCVAR_NONE, "Mortar's starburst maximum damage" );
|
||
|
ConVar weapon_mortar_starburst_radius( "weapon_mortar_starburst_radius","0", FCVAR_NONE, "Mortar's starburst splash radius" );
|
||
|
ConVar weapon_mortar_cluster_shells( "weapon_mortar_cluster_shells","0", FCVAR_NONE, "Number of shells a mortar cluster round bursts into" );
|
||
|
|
||
|
|
||
|
//=====================================================================================================
|
||
|
// MORTAR WEAPON
|
||
|
//=====================================================================================================
|
||
|
LINK_ENTITY_TO_CLASS( weapon_mortar, CWeaponMortar );
|
||
|
PRECACHE_WEAPON_REGISTER(weapon_mortar);
|
||
|
|
||
|
EXTERN_SEND_TABLE(DT_BaseCombatWeapon)
|
||
|
|
||
|
IMPLEMENT_SERVERCLASS_ST(CWeaponMortar, DT_WeaponMortar)
|
||
|
SendPropInt( SENDINFO( m_bCarried ), 2, SPROP_UNSIGNED ),
|
||
|
SendPropInt( SENDINFO( m_bMortarReloading ), 2, SPROP_UNSIGNED ),
|
||
|
SendPropVector( SENDINFO(m_vecMortarOrigin), -1, SPROP_COORD ),
|
||
|
SendPropVector( SENDINFO(m_vecMortarAngles), -1, SPROP_COORD ),
|
||
|
END_SEND_TABLE()
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CWeaponMortar::CWeaponMortar( void )
|
||
|
{
|
||
|
#ifdef _DEBUG
|
||
|
m_vecMortarOrigin.Init();
|
||
|
m_vecMortarAngles.Init();
|
||
|
#endif
|
||
|
|
||
|
m_bCarried = true;
|
||
|
m_bMortarReloading = false;
|
||
|
m_hDeployedMortar = NULL;
|
||
|
m_bRangeUpgraded = false;
|
||
|
m_bAccuracyUpgraded = false;
|
||
|
}
|
||
|
|
||
|
void CWeaponMortar::Precache()
|
||
|
{
|
||
|
BaseClass::Precache();
|
||
|
|
||
|
PrecacheScriptSound( "WeaponMortar.EMPed" );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
float CWeaponMortar::GetFireRate( void )
|
||
|
{
|
||
|
return 3.0;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CWeaponMortar::Deploy( )
|
||
|
{
|
||
|
return DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), ACT_SLAM_TRIPMINE_DRAW, (char*)GetAnimPrefix() );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponMortar::ItemPostFrame( void )
|
||
|
{
|
||
|
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
|
||
|
if (pPlayer == NULL)
|
||
|
return;
|
||
|
|
||
|
if ( pPlayer->m_nButtons & IN_ATTACK )
|
||
|
{
|
||
|
if ( m_bCarried )
|
||
|
{
|
||
|
ClientPrint( pPlayer, HUD_PRINTCENTER, "\n\n\n\n\n\n\n\n\n\nBuild your mortar with the build weapon first!" );
|
||
|
}
|
||
|
}
|
||
|
else if ( pPlayer->m_nButtons & IN_ATTACK2 )
|
||
|
{
|
||
|
SecondaryAttack();
|
||
|
}
|
||
|
|
||
|
// No buttons down.
|
||
|
if (!(( pPlayer->m_nButtons & IN_ATTACK ) || ( pPlayer->m_nButtons & IN_ATTACK2 )))
|
||
|
{
|
||
|
WeaponIdle();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Output : Returns true on success, false on failure.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CWeaponMortar::ComputeEMPFireState( void )
|
||
|
{
|
||
|
if (IsOwnerEMPed())
|
||
|
{
|
||
|
CPASAttenuationFilter filter( GetOwner(), "WeaponMortar.EMPed" );
|
||
|
EmitSound( filter, GetOwner()->entindex(), "WeaponMortar.EMPed" );
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponMortar::PrimaryAttack( void )
|
||
|
{
|
||
|
CBaseTFPlayer *pPlayer = ToBaseTFPlayer( GetOwner() );
|
||
|
if ( !pPlayer )
|
||
|
return;
|
||
|
// Can't attack if taking EMP damage
|
||
|
if ( !ComputeEMPFireState() )
|
||
|
return;
|
||
|
if ( IsOwnerEMPed() )
|
||
|
return;
|
||
|
if ( m_hDeployedMortar == NULL )
|
||
|
return;
|
||
|
|
||
|
if ( m_hDeployedMortar->FireMortar( m_flFiringPower, m_flFiringAccuracy, m_bRangeUpgraded, m_bAccuracyUpgraded ) )
|
||
|
{
|
||
|
WeaponSound( SINGLE );
|
||
|
}
|
||
|
|
||
|
m_flNextPrimaryAttack = gpGlobals->curtime + 0.5;
|
||
|
m_flNextSecondaryAttack = gpGlobals->curtime + 0.5;
|
||
|
|
||
|
CheckRemoveDisguise();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponMortar::Fire( float flPower, float flAccuracy )
|
||
|
{
|
||
|
m_flFiringPower = flPower;
|
||
|
m_flFiringAccuracy = flAccuracy;
|
||
|
|
||
|
PrimaryAttack();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponMortar::SecondaryAttack( void )
|
||
|
{
|
||
|
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
|
||
|
if ( !pPlayer )
|
||
|
return;
|
||
|
|
||
|
// Setup for refire
|
||
|
m_flNextPrimaryAttack = gpGlobals->curtime + 0.5;
|
||
|
m_flNextSecondaryAttack = gpGlobals->curtime + 1.0;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Player's finished deploying his mortar
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponMortar::DeployMortar( CObjectMortar *pMortar )
|
||
|
{
|
||
|
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
|
||
|
if ( !pPlayer )
|
||
|
return;
|
||
|
|
||
|
ClientPrint( pPlayer, HUD_PRINTCENTER, "\n\n\n\n\n\n\n\n\n\nMortar Deployed" );
|
||
|
|
||
|
m_bCarried = false;
|
||
|
m_hDeployedMortar = pMortar;
|
||
|
m_hDeployedMortar->m_hMortarWeapon = this;
|
||
|
SendWeaponAnim( ACT_SLAM_DETONATOR_DRAW );
|
||
|
|
||
|
m_vecMortarOrigin = m_hDeployedMortar->GetLocalOrigin();
|
||
|
m_vecMortarAngles = m_hDeployedMortar->GetLocalAngles();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Mortar object has been removed
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponMortar::MortarObjectRemoved( void )
|
||
|
{
|
||
|
m_hDeployedMortar = NULL;
|
||
|
m_bCarried = true;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponMortar::SetYaw( float flYaw )
|
||
|
{
|
||
|
if ( m_hDeployedMortar == NULL )
|
||
|
return;
|
||
|
|
||
|
QAngle angles = m_hDeployedMortar->GetLocalAngles();
|
||
|
angles.y = flYaw;
|
||
|
m_hDeployedMortar->SetLocalAngles( angles );
|
||
|
m_vecMortarAngles = angles;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Set the deployed mortar's firing round
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponMortar::SetRoundType( int iRoundType )
|
||
|
{
|
||
|
if ( m_hDeployedMortar == NULL )
|
||
|
return;
|
||
|
|
||
|
// Make sure we've got the technology for this round type
|
||
|
if ( MortarAmmoTechs[ iRoundType ] && MortarAmmoTechs[ iRoundType ][0] )
|
||
|
{
|
||
|
CBaseTFPlayer *pPlayer = ToBaseTFPlayer( GetOwner() );
|
||
|
if ( !pPlayer )
|
||
|
return;
|
||
|
// Does the player have the technology?
|
||
|
if ( pPlayer->HasNamedTechnology( MortarAmmoTechs[ iRoundType ] ) == false )
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
m_hDeployedMortar->m_iRoundType = iRoundType;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponMortar::MortarDestroyed( void )
|
||
|
{
|
||
|
CBaseTFPlayer *pPlayer = ToBaseTFPlayer( GetOwner() );
|
||
|
if ( pPlayer )
|
||
|
{
|
||
|
ClientPrint( pPlayer, HUD_PRINTCENTER, "\n\n\n\n\n\n\n\n\n\nMortar Destroyed!" );
|
||
|
}
|
||
|
|
||
|
if ( pPlayer && pPlayer->GetActiveWeapon() == this )
|
||
|
{
|
||
|
SendWeaponAnim( ACT_SLAM_TRIPMINE_DRAW );
|
||
|
}
|
||
|
|
||
|
MortarObjectRemoved();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Input : *pObject -
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponMortar::AddAssociatedObject( CBaseObject *pObject )
|
||
|
{
|
||
|
Assert( pObject );
|
||
|
|
||
|
// Can't handle this object
|
||
|
CObjectMortar *mortar = dynamic_cast< CObjectMortar * >( pObject );
|
||
|
if ( !mortar )
|
||
|
return;
|
||
|
|
||
|
m_bCarried = false;
|
||
|
|
||
|
m_hDeployedMortar = mortar;
|
||
|
mortar->m_hMortarWeapon = this;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// Input : *pObject -
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponMortar::RemoveAssociatedObject( CBaseObject *pObject )
|
||
|
{
|
||
|
Assert( pObject );
|
||
|
|
||
|
// Can't handle this object
|
||
|
CObjectMortar *mortar = dynamic_cast< CObjectMortar * >( pObject );
|
||
|
if ( !mortar )
|
||
|
return;
|
||
|
|
||
|
if ( m_hDeployedMortar == mortar )
|
||
|
{
|
||
|
m_hDeployedMortar = NULL;
|
||
|
m_bCarried = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: The player holding this weapon has just gained new technology.
|
||
|
// Check to see if it affects the mortar
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponMortar::GainedNewTechnology( CBaseTechnology *pTechnology )
|
||
|
{
|
||
|
CBaseTFPlayer *pPlayer = ToBaseTFPlayer( GetOwner() );
|
||
|
if ( pPlayer )
|
||
|
{
|
||
|
// Range upgraded?
|
||
|
if ( pPlayer->HasNamedTechnology("mortar_range") )
|
||
|
m_bRangeUpgraded = true;
|
||
|
else
|
||
|
m_bRangeUpgraded = false;
|
||
|
|
||
|
// Accuracy upgraded?
|
||
|
if ( pPlayer->HasNamedTechnology("mortar_accuracy") )
|
||
|
m_bAccuracyUpgraded = true;
|
||
|
else
|
||
|
m_bAccuracyUpgraded = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponMortar::WeaponIdle( void )
|
||
|
{
|
||
|
if ( HasWeaponIdleTimeElapsed() )
|
||
|
{
|
||
|
if ( m_bCarried )
|
||
|
{
|
||
|
SendWeaponAnim( ACT_SLAM_TRIPMINE_IDLE );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SendWeaponAnim( ACT_SLAM_DETONATOR_IDLE );
|
||
|
}
|
||
|
|
||
|
SetWeaponIdleTime( gpGlobals->curtime + 1.0 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: My mortar object is reloading
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponMortar::MortarIsReloading( void )
|
||
|
{
|
||
|
m_bMortarReloading = true;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: My mortar object has finished reloading
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CWeaponMortar::MortarFinishedReloading( void )
|
||
|
{
|
||
|
m_bMortarReloading = false;
|
||
|
}
|