Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
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.
 
 
 
 
 
 

367 lines
11 KiB

//========= 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;
}