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
278 lines
7.9 KiB
![]()
4 years ago
|
//========= 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 );
|
||
|
}
|
||
|
}
|