Пример #1
0
//-----------------------------------------------------------------------------
// Purpose: Add damage to the existing multidamage, and apply if it won't fit
//-----------------------------------------------------------------------------
void AddMultiDamage( const CTakeDamageInfo &info, CBaseEntity *pEntity )
{
	if ( !pEntity )
		return;

	if ( pEntity != g_MultiDamage.GetTarget() )
	{
		ApplyMultiDamage();
		g_MultiDamage.Init( pEntity, info.GetInflictor(), info.GetAttacker(), info.GetWeapon(), vec3_origin, vec3_origin, vec3_origin, 0.0, info.GetDamageType(), info.GetDamageCustom() );
	}

	g_MultiDamage.AddDamageType( info.GetDamageType() );
	g_MultiDamage.SetDamage( g_MultiDamage.GetDamage() + info.GetDamage() );
	g_MultiDamage.SetDamageForce( g_MultiDamage.GetDamageForce() + info.GetDamageForce() );
	g_MultiDamage.SetDamagePosition( info.GetDamagePosition() );
	g_MultiDamage.SetReportedPosition( info.GetReportedPosition() );
	g_MultiDamage.SetMaxDamage( MAX( g_MultiDamage.GetMaxDamage(), info.GetDamage() ) );
	g_MultiDamage.SetAmmoType( info.GetAmmoType() );

	if ( g_MultiDamage.GetPlayerPenetrationCount() == 0 )
	{
		g_MultiDamage.SetPlayerPenetrationCount( info.GetPlayerPenetrationCount() );
	}

	bool bHasPhysicsForceDamage = !g_pGameRules->Damage_NoPhysicsForce( info.GetDamageType() );
	if ( bHasPhysicsForceDamage && g_MultiDamage.GetDamageType() != DMG_GENERIC )
	{
		// If you hit this assert, you've called TakeDamage with a damage type that requires a physics damage
		// force & position without specifying one or both of them. Decide whether your damage that's causing 
		// this is something you believe should impart physics force on the receiver. If it is, you need to 
		// setup the damage force & position inside the CTakeDamageInfo (Utility functions for this are in
		// takedamageinfo.cpp. If you think the damage shouldn't cause force (unlikely!) then you can set the 
		// damage type to DMG_GENERIC, or | DMG_CRUSH if you need to preserve the damage type for purposes of HUD display.
		if ( g_MultiDamage.GetDamageForce() == vec3_origin || g_MultiDamage.GetDamagePosition() == vec3_origin )
		{
			static int warningCount = 0;
			if ( ++warningCount < 10 )
			{
				if ( g_MultiDamage.GetDamageForce() == vec3_origin )
				{
					Warning( "AddMultiDamage:  g_MultiDamage.GetDamageForce() == vec3_origin\n" );
				}

				if ( g_MultiDamage.GetDamagePosition() == vec3_origin)
				{
					Warning( "AddMultiDamage:  g_MultiDamage.GetDamagePosition() == vec3_origin\n" );
				}
			}
		}
	}
}
Пример #2
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CTFGameStats::Event_PlayerDamage( CBasePlayer *pBasePlayer, const CTakeDamageInfo &info, int iDamageTaken )
{
	CObjectSentrygun *pSentry = NULL;
	CTFPlayer *pTarget = ToTFPlayer( pBasePlayer );
	CTFPlayer *pAttacker = ToTFPlayer( info.GetAttacker() );
	if ( !pAttacker )
	{
		pSentry = dynamic_cast< CObjectSentrygun * >( info.GetAttacker() );
		if ( !pSentry )
			return;

		pAttacker = pSentry->GetOwner();
		if ( !pAttacker )
		{
			// Sentry with no builder? Must be a pre-placed sentry.
			// It's easier to just cut off here and don't count damage.
			return;
		}
	}
	// don't count damage to yourself
	if ( pTarget == pAttacker )
		return;
	
	IncrementStat( pAttacker, TFSTAT_DAMAGE, iDamageTaken );

	TF_Gamestats_LevelStats_t::PlayerDamageLump_t damage;
	Vector killerOrg;

	// set the location where the target was hit
	const Vector &org = pTarget->GetAbsOrigin();
	damage.nTargetPosition[ 0 ] = static_cast<int>( org.x );
	damage.nTargetPosition[ 1 ] = static_cast<int>( org.y );
	damage.nTargetPosition[ 2 ] = static_cast<int>( org.z );

	// set the class of the attacker
	CBaseEntity *pInflictor = info.GetInflictor();
	CBasePlayer *pScorer = TFGameRules()->GetDeathScorer( pAttacker, pInflictor, pTarget );

	if ( !pSentry )
	{
		pSentry = dynamic_cast< CObjectSentrygun * >( pInflictor );
	}

	if ( pSentry != NULL )
	{
		killerOrg = pSentry->GetAbsOrigin();
		damage.iAttackClass = TF_CLASS_ENGINEER;
		damage.iWeapon = ( info.GetDamageType() & DMG_BLAST ) ? TF_WEAPON_SENTRY_ROCKET : TF_WEAPON_SENTRY_BULLET;
	} 
	else if ( dynamic_cast<CObjectDispenser *>( pInflictor ) )
	{
		damage.iAttackClass = TF_CLASS_ENGINEER;
		damage.iWeapon = TF_WEAPON_DISPENSER;
	}
	else
	{
		CTFPlayer *pTFAttacker = ToTFPlayer( pScorer );
		if ( pTFAttacker )
		{
			CTFPlayerClass *pAttackerClass = pTFAttacker->GetPlayerClass();
			damage.iAttackClass = ( !pAttackerClass ) ? TF_CLASS_UNDEFINED : pAttackerClass->GetClassIndex();
			killerOrg = pTFAttacker->GetAbsOrigin();
		}
		else
		{
			damage.iAttackClass = TF_CLASS_UNDEFINED;
			killerOrg = org;
		}

		// find the weapon the killer used
		damage.iWeapon = GetWeaponFromDamage( info );
	}

	// If normal gameplay state, track weapon stats. 
	if ( ( TFGameRules()->State_Get() == GR_STATE_RND_RUNNING ) && ( damage.iWeapon != TF_WEAPON_NONE  ) )
	{
		// record hits & damage in reported per-weapon stats
		if ( m_reportedStats.m_pCurrentGame != NULL )
		{
			TF_Gamestats_WeaponStats_t *pWeaponStats = &m_reportedStats.m_pCurrentGame->m_aWeaponStats[damage.iWeapon];
			pWeaponStats->iHits++;
			pWeaponStats->iTotalDamage += iDamageTaken;

			// Try and figure out where the damage is coming from
			Vector vecDamageOrigin = info.GetReportedPosition();
			// If we didn't get an origin to use, try using the attacker's origin
			if ( vecDamageOrigin == vec3_origin )
			{
				if ( pSentry )
				{
					vecDamageOrigin = pSentry->GetAbsOrigin();
				}
				else
				{
					vecDamageOrigin = killerOrg;
				}					
			}
			if ( vecDamageOrigin != vec3_origin )
			{
				pWeaponStats->iHitsWithKnownDistance++;
				int iDistance = (int) vecDamageOrigin.DistTo( pBasePlayer->GetAbsOrigin() );
//				Msg( "Damage distance: %d\n", iDistance );
				pWeaponStats->iTotalDistance += iDistance;
			}
		}
	}

	Assert( damage.iAttackClass != TF_CLASS_UNDEFINED );

	// record the time the damage occurred
	damage.fTime = gpGlobals->curtime;

	// store the attacker's position
	damage.nAttackerPosition[ 0 ] = static_cast<int>( killerOrg.x );
	damage.nAttackerPosition[ 1 ] = static_cast<int>( killerOrg.y );
	damage.nAttackerPosition[ 2 ] = static_cast<int>( killerOrg.z );

	// set the class of the target
	CTFPlayer *pTFPlayer = ToTFPlayer( pTarget );
	CTFPlayerClass *pTargetClass = ( pTFPlayer ) ? pTFPlayer->GetPlayerClass() : NULL;
	damage.iTargetClass = ( !pTargetClass ) ? TF_CLASS_UNDEFINED : pTargetClass->GetClassIndex();

	Assert( damage.iTargetClass != TF_CLASS_UNDEFINED );

	// record the damage done
	damage.iDamage = info.GetDamage();

	// record if it was a crit
	damage.iCrit = ( ( info.GetDamageType() & DMG_CRITICAL ) != 0 );

	// record if it was a kill
	damage.iKill = ( pTarget->GetHealth() <= 0 );

	// add it to the list of damages
	if ( m_reportedStats.m_pCurrentGame != NULL )
	{
		m_reportedStats.m_pCurrentGame->m_aPlayerDamage.AddToTail( damage );
	}	
}