Team Fortress 2 Source Code as on 22/4/2020
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.
 
 
 
 
 
 

278 lines
7.9 KiB

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: TF Base Rockets.
//
//=============================================================================//
#include "cbase.h"
#include "tf_wearable_item_demoshield.h"
#include "tf_gamerules.h"
#include "engine/ivdebugoverlay.h"
#include "tf_weapon_medigun.h"
#ifdef CLIENT_DLL
#include "tf_weapon_sword.h"
#include "renamed_recvtable_compat.h"
NOTE_RENAMED_RECVTABLE( DT_TFWearableItemDemoShield, DT_TFWearableDemoShield )
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
LINK_ENTITY_TO_CLASS( tf_wearable_demoshield, CTFWearableDemoShield );
IMPLEMENT_NETWORKCLASS_ALIASED( TFWearableDemoShield, DT_TFWearableDemoShield )
// Network Table --
BEGIN_NETWORK_TABLE( CTFWearableDemoShield, DT_TFWearableDemoShield )
#if defined( GAME_DLL )
#else
#endif // GAME_DLL
END_NETWORK_TABLE()
// -- Network Table
// Data Desc --
BEGIN_DATADESC( CTFWearableDemoShield )
END_DATADESC()
// -- Data Desc
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CTFWearableDemoShield::CTFWearableDemoShield() : CTFWearable()
{
#ifdef GAME_DLL
m_bImpactedSomething = false;
#endif
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFWearableDemoShield::Precache()
{
BaseClass::Precache();
PrecacheScriptSound( "DemoCharge.HitWorld" );
PrecacheScriptSound( "DemoCharge.HitFlesh" );
PrecacheScriptSound( "DemoCharge.HitFleshRange" );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFWearableDemoShield::DoSpecialAction( CTFPlayer *pPlayer )
{
if ( CanCharge( pPlayer ) )
{
DoCharge( pPlayer );
return;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFWearableDemoShield::EndSpecialAction( CTFPlayer *pPlayer )
{
int nAttackNotCancelCharge = 0;
CALL_ATTRIB_HOOK_INT( nAttackNotCancelCharge, attack_not_cancel_charge );
if ( nAttackNotCancelCharge > 0 )
{
return;
}
if ( pPlayer->m_Shared.InCond( TF_COND_SHIELD_CHARGE ) )
{
pPlayer->m_Shared.CalcChargeCrit();
pPlayer->m_Shared.SetDemomanChargeMeter( 0 );
pPlayer->m_Shared.RemoveCond( TF_COND_SHIELD_CHARGE );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CTFWearableDemoShield::CanCharge( CTFPlayer *pPlayer )
{
// 6/14/2011 - Demos can now charge while in the air to counter pyro control.
// if ( !(pPlayer->GetFlags() & FL_ONGROUND) )
// return false;
if ( TFGameRules() && (TFGameRules()->State_Get() == GR_STATE_PREROUND) )
return false;
if ( pPlayer->m_Shared.IsLoser() )
return false;
if ( pPlayer->m_Shared.InCond( TF_COND_STUNNED ) )
return false;
if ( pPlayer->IsTaunting() )
return false;
if ( pPlayer->GetGrapplingHookTarget() )
return false;
if ( pPlayer->m_Shared.GetDemomanChargeMeter() == 100.f )
return true;
if ( TFGameRules() && TFGameRules()->IsPasstimeMode() && pPlayer->m_Shared.HasPasstimeBall() )
return false;
return false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFWearableDemoShield::DoCharge( CTFPlayer *pPlayer )
{
#ifdef GAME_DLL
float flChargeTime = 1.5f;
CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( pPlayer, flChargeTime, mod_charge_time );
pPlayer->m_Shared.AddCond( TF_COND_SHIELD_CHARGE, flChargeTime );
m_bImpactedSomething = false;
#endif
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFWearableDemoShield::ShieldBash( CTFPlayer *pPlayer, float flCurrentChargeMeter )
{
CTFPlayer *pOwner = ToTFPlayer( GetOwnerEntity() );
if ( !pOwner )
return;
#ifdef GAME_DLL
if ( m_bImpactedSomething )
return;
m_bImpactedSomething = true;
// Setup the swing range.
Vector vecForward;
AngleVectors( pOwner->EyeAngles(), &vecForward );
Vector vecStart = pOwner->Weapon_ShootPosition();
Vector vecEnd = vecStart + vecForward * 48;
// See if we hit anything.
trace_t trace;
UTIL_TraceHull( vecStart, vecEnd, -Vector(24,24,24), Vector(24,24,24),
MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &trace );
// Play an impact sound.
bool bImpactDamage = false;
if ( trace.m_pEnt )
{
const char* pszSoundName = "";
if ( trace.m_pEnt->IsPlayer() )
{
bImpactDamage = true;
pszSoundName = "DemoCharge.HitFleshRange";
}
else
{
pszSoundName = "DemoCharge.HitWorld";
}
pOwner->EmitSound( pszSoundName );
}
// Apply impact damage, if any.
if ( bImpactDamage )
{
float flBashDamage = CalculateChargeDamage( flCurrentChargeMeter );
CTakeDamageInfo info;
info.SetAttacker( pOwner );
info.SetInflictor( this );
info.SetWeapon( this );
info.SetDamage( flBashDamage );
info.SetDamageCustom( TF_DMG_CUSTOM_CHARGE_IMPACT );
info.SetDamageForce( GetShieldDamageForce( flCurrentChargeMeter ) );
info.SetDamagePosition( trace.endpos );
info.SetDamageType( DMG_CLUB );
Vector dir;
AngleVectors( pOwner->GetAbsAngles(), &dir );
trace.m_pEnt->DispatchTraceAttack( info, dir, &trace );
ApplyMultiDamage();
// Calculate charge crit if we did any bash damage
pOwner->m_Shared.CalcChargeCrit();
}
UTIL_ScreenShake( pOwner->WorldSpaceCenter(), 25.0, 150.0, 1.0, 750, SHAKE_START );
#endif
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
float CTFWearableDemoShield::CalculateChargeDamage( float flCurrentChargeMeter )
{
float flImpactDamage = RemapValClamped( flCurrentChargeMeter, 90.0f, 40.0f, 15.0f, 50.0f );
CTFPlayer *pOwner = ToTFPlayer( GetOwnerEntity() );
if ( !pOwner )
return flImpactDamage;
// Cap at 5 decapitations for dmg bonus
int iDecaps = Min( pOwner->m_Shared.GetDecapitations(), 5 );
if ( iDecaps > 0 )
{
flImpactDamage *= (1.0f + iDecaps * 0.1f );
}
CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( pOwner, flImpactDamage, charge_impact_damage );
return flImpactDamage;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
Vector CTFWearableDemoShield::GetShieldDamageForce( float flCurrentChargeMeter )
{
Vector vecVelocity = GetAbsVelocity();
IPhysicsObject *pPhysicsObject = VPhysicsGetObject();
if ( pPhysicsObject )
{
pPhysicsObject->GetVelocity( &vecVelocity, NULL );
VectorNormalize( vecVelocity );
}
return (vecVelocity * CalculateChargeDamage( flCurrentChargeMeter ) );
}
//-----------------------------------------------------------------------------
// Purpose: Attaches the item to the player.
//-----------------------------------------------------------------------------
void CTFWearableDemoShield::Equip( CBasePlayer* pOwner )
{
BaseClass::Equip( pOwner );
if ( !CanEquip( pOwner ) )
return;
CTFPlayer *pTFPlayer = ToTFPlayer( pOwner );
if ( pTFPlayer )
{
pTFPlayer->m_Shared.SetShieldEquipped( true );
}
}
//-----------------------------------------------------------------------------
// Purpose: Remove item from the player.
//-----------------------------------------------------------------------------
void CTFWearableDemoShield::UnEquip( CBasePlayer* pOwner )
{
BaseClass::UnEquip( pOwner );
CTFPlayer *pTFPlayer = ToTFPlayer( pOwner );
if ( pTFPlayer )
{
pTFPlayer->m_Shared.SetShieldEquipped( false );
}
}