//-----------------------------------------------------------------------------
// Purpose: 
// Input  : &info - 
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
void CNPC_CombineShot::Event_Killed(const CTakeDamageInfo &info)
{
	// Don't bother if we've been told not to, or the player has a megaphyscannon
	if ( combine_shot_spawn_health.GetBool() == false || PlayerHasMegaPhysCannon() )
	{
		BaseClass::Event_Killed( info );
		return;
	}

	CBasePlayer *pPlayer = ToBasePlayer( info.GetAttacker() );

	if ( !pPlayer )
	{
		CPropVehicleDriveable *pVehicle = dynamic_cast<CPropVehicleDriveable *>( info.GetAttacker() ) ;
		if ( pVehicle && pVehicle->GetDriver() && pVehicle->GetDriver()->IsPlayer() )
		{
			pPlayer = assert_cast<CBasePlayer *>( pVehicle->GetDriver() );
		}
	}

	if ( pPlayer != NULL )
	{
		CHalfLife2 *pHL2GameRules = static_cast<CHalfLife2 *>(g_pGameRules);

		// Attempt to drop health
		if ( pHL2GameRules->NPC_ShouldDropHealth( pPlayer ) )
		{
			DropItem( "item_healthvial", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) );
			pHL2GameRules->NPC_DroppedHealth();
		}
		
		if ( HasSpawnFlags( SF_COMBINE_NO_GRENADEDROP ) == false )
		{
			// Attempt to drop a grenade
			if ( pHL2GameRules->NPC_ShouldDropGrenade( pPlayer ) )
			{
				DropItem( "weapon_frag", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) );
				pHL2GameRules->NPC_DroppedGrenade();
			}
		}
	}

	BaseClass::Event_Killed( info );
}
Exemplo n.º 2
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CEP2GameStats::Event_PlayerKilledOther( CBasePlayer *pAttacker, CBaseEntity *pVictim, const CTakeDamageInfo &info )
{
	BaseClass::Event_PlayerKilledOther( pAttacker, pVictim, info );

	if ( pAttacker )
	{
		StatsLog( "Attacker: %s\n", pAttacker->GetClassname() );
	}
	
	if ( !pVictim  )
	{
		return;
	}

	char const *pchVictim = pVictim->GetClassname();
	Ep2LevelStats_t::EntityDeathsLump_t *lump = FindDeathsLump( pchVictim );
	if ( lump )
	{
		++lump->m_nBodyCount;
		StatsLog( "Player has killed %d %s's\n", lump->m_nBodyCount, pchVictim );

		CPropVehicleDriveable *veh = dynamic_cast< CPropVehicleDriveable * >( pAttacker );
		if ( !veh )
			veh = dynamic_cast< CPropVehicleDriveable * >( info.GetInflictor() );
		if ( veh )
		{
			CBaseEntity *driver = veh->GetDriver();
			if ( driver && driver->IsPlayer() )
			{
				++m_pCurrentMap->m_IntCounters[ Ep2LevelStats_t::COUNTER_VEHICULARHOMICIDES ];
				StatsLog( "  Vehicular homicide [%I64d] of %s's\n", m_pCurrentMap->m_IntCounters[ Ep2LevelStats_t::COUNTER_VEHICULARHOMICIDES ], pchVictim );
			}
		}
	}
	else
	{
		StatsLog( "Player killed %s (not tracked)\n", pchVictim );
	}
}
//-----------------------------------------------------------------------------
// Purpose: Vehicle dampening shared between server and client
//-----------------------------------------------------------------------------
void SharedVehicleViewSmoothing(CBasePlayer *pPlayer,
                                Vector *pAbsOrigin, QAngle *pAbsAngles,
                                bool bEnterAnimOn, bool bExitAnimOn,
                                const Vector &vecEyeExitEndpoint,
                                ViewSmoothingData_t *pData,
                                float *pFOV )
{
    int eyeAttachmentIndex = pData->pVehicle->LookupAttachment( "vehicle_driver_eyes" );
    matrix3x4_t vehicleEyePosToWorld;
    Vector vehicleEyeOrigin;
    QAngle vehicleEyeAngles;
    pData->pVehicle->GetAttachment( eyeAttachmentIndex, vehicleEyeOrigin, vehicleEyeAngles );
    AngleMatrix( vehicleEyeAngles, vehicleEyePosToWorld );

    // Dampen the eye positional change as we drive around.
    *pAbsAngles = pPlayer->EyeAngles();
    if ( r_VehicleViewDampen.GetInt() && pData->bDampenEyePosition )
    {
        CPropVehicleDriveable *pDriveable = assert_cast<CPropVehicleDriveable*>(pData->pVehicle);
        pDriveable->DampenEyePosition( vehicleEyeOrigin, vehicleEyeAngles );
    }

    // Started running an entry or exit anim?
    bool bRunningAnim = ( bEnterAnimOn || bExitAnimOn );
    if ( bRunningAnim && !pData->bWasRunningAnim )
    {
        pData->bRunningEnterExit = true;
        pData->flEnterExitStartTime = gpGlobals->curtime;
        pData->flEnterExitDuration = pData->pVehicle->SequenceDuration( pData->pVehicle->GetSequence() );

#ifdef CLIENT_DLL
        pData->vecOriginSaved = PrevMainViewOrigin();
        pData->vecAnglesSaved = PrevMainViewAngles();
#endif

        // Save our initial angular error, which we will blend out over the length of the animation.
        pData->vecAngleDiffSaved.x = AngleDiff( vehicleEyeAngles.x, pData->vecAnglesSaved.x );
        pData->vecAngleDiffSaved.y = AngleDiff( vehicleEyeAngles.y, pData->vecAnglesSaved.y );
        pData->vecAngleDiffSaved.z = AngleDiff( vehicleEyeAngles.z, pData->vecAnglesSaved.z );

        pData->vecAngleDiffMin = pData->vecAngleDiffSaved;
    }

    pData->bWasRunningAnim = bRunningAnim;

    float frac = 0;
    float flFracFOV = 0;

    // If we're in an enter/exit animation, blend the player's eye angles to the attachment's
    if ( bRunningAnim || pData->bRunningEnterExit )
    {
        *pAbsAngles = vehicleEyeAngles;

        // Forward integrate to determine the elapsed time in this entry/exit anim.
        frac = ( gpGlobals->curtime - pData->flEnterExitStartTime ) / pData->flEnterExitDuration;
        frac = clamp( frac, 0.0f, 1.0f );

        flFracFOV = ( gpGlobals->curtime - pData->flEnterExitStartTime ) / ( pData->flEnterExitDuration * 0.85f );
        flFracFOV = clamp( flFracFOV, 0.0f, 1.0f );

        //Msg("Frac: %f\n", frac );

        if ( frac < 1.0 )
        {
            // Blend to the desired vehicle eye origin
            //Vector vecToView = (vehicleEyeOrigin - PrevMainViewOrigin());
            //vehicleEyeOrigin = PrevMainViewOrigin() + (vecToView * SimpleSpline(frac));
            //debugoverlay->AddBoxOverlay( vehicleEyeOrigin, -Vector(1,1,1), Vector(1,1,1), vec3_angle, 0,255,255, 64, 10 );
        }
        else
        {
            pData->bRunningEnterExit = false;

            // Enter animation has finished, align view with the eye attachment point
            // so they can start mouselooking around.
#if !defined ( HL2MP_DEV_DLL ) && !defined ( HL2MP_DEV_VEHICLE_FIX )
            if ( !bExitAnimOn )
            {
                Vector localEyeOrigin;
                QAngle localEyeAngles;

                pData->pVehicle->GetAttachmentLocal( eyeAttachmentIndex, localEyeOrigin, localEyeAngles );
#ifdef CLIENT_DLL
                engine->SetViewAngles( localEyeAngles );
#endif
            }
#else

#ifdef CLIENT_DLL
            pPlayer = C_BasePlayer::GetLocalPlayer();
#endif
            if ( pPlayer )
            {
                if ( !bExitAnimOn )
                {
                    Vector localEyeOrigin;
                    QAngle localEyeAngles;

                    pData->pVehicle->GetAttachmentLocal( eyeAttachmentIndex, localEyeOrigin, localEyeAngles );
#ifdef CLIENT_DLL
                    engine->SetViewAngles( localEyeAngles );
#endif
                }
            }
#endif
        }
    }

    // Compute the relative rotation between the unperturbed eye attachment + the eye angles
    matrix3x4_t cameraToWorld;
    AngleMatrix( *pAbsAngles, cameraToWorld );

    matrix3x4_t worldToEyePos;
    MatrixInvert( vehicleEyePosToWorld, worldToEyePos );

    matrix3x4_t vehicleCameraToEyePos;
    ConcatTransforms( worldToEyePos, cameraToWorld, vehicleCameraToEyePos );

    // Damp out some of the vehicle motion (neck/head would do this)
    if ( pData->bClampEyeAngles )
    {
        RemapViewAngles( pData, vehicleEyeAngles );
    }

    AngleMatrix( vehicleEyeAngles, vehicleEyeOrigin, vehicleEyePosToWorld );

    // Now treat the relative eye angles as being relative to this new, perturbed view position...
    matrix3x4_t newCameraToWorld;
    ConcatTransforms( vehicleEyePosToWorld, vehicleCameraToEyePos, newCameraToWorld );

    // output new view abs angles
    MatrixAngles( newCameraToWorld, *pAbsAngles );

    // UNDONE: *pOrigin would already be correct in single player if the HandleView() on the server ran after vphysics
    MatrixGetColumn( newCameraToWorld, 3, *pAbsOrigin );

    float flDefaultFOV;
#ifdef CLIENT_DLL
    flDefaultFOV = default_fov.GetFloat();
#else
    flDefaultFOV = pPlayer->GetDefaultFOV();
#endif

    // If we're playing an entry or exit animation...
    if ( bRunningAnim || pData->bRunningEnterExit )
    {
        float flSplineFrac = clamp( SimpleSpline( frac ), 0.f, 1.f );

        // Blend out the error between the player's initial eye angles and the animation's initial
        // eye angles over the duration of the animation.
        QAngle vecAngleDiffBlend = ( ( 1 - flSplineFrac ) * pData->vecAngleDiffSaved );

        // If our current error is less than the error amount that we're blending
        // out, use that. This lets the angles converge as quickly as possible.
        QAngle vecAngleDiffCur;
        vecAngleDiffCur.x = AngleDiff( vehicleEyeAngles.x, pData->vecAnglesSaved.x );
        vecAngleDiffCur.y = AngleDiff( vehicleEyeAngles.y, pData->vecAnglesSaved.y );
        vecAngleDiffCur.z = AngleDiff( vehicleEyeAngles.z, pData->vecAnglesSaved.z );

        // In either case, never increase the error, so track the minimum error and clamp to that.
        for (int i = 0; i < 3; i++)
        {
            if ( fabs(vecAngleDiffCur[i] ) < fabs( pData->vecAngleDiffMin[i] ) )
            {
                pData->vecAngleDiffMin[i] = vecAngleDiffCur[i];
            }

            if ( fabs(vecAngleDiffBlend[i] ) < fabs( pData->vecAngleDiffMin[i] ) )
            {
                pData->vecAngleDiffMin[i] = vecAngleDiffBlend[i];
            }
        }

        // Add the error to the animation's eye angles.
        *pAbsAngles -= pData->vecAngleDiffMin;

        // Use this as the basis for the next error calculation.
        pData->vecAnglesSaved = *pAbsAngles;

        //if ( gpGlobals->frametime )
        //{
        //	Msg("Angle : %.2f %.2f %.2f\n", target.x, target.y, target.z );
        //}
        //Msg("Prev: %.2f %.2f %.2f\n", pData->vecAnglesSaved.x, pData->vecAnglesSaved.y, pData->vecAnglesSaved.z );

        Vector vecAbsOrigin = *pAbsOrigin;

        // If we're exiting, our desired position is the server-sent exit position
        if ( bExitAnimOn )
        {
            //debugoverlay->AddBoxOverlay( vecEyeExitEndpoint, -Vector(1,1,1), Vector(1,1,1), vec3_angle, 255,255,255, 64, 10 );

            // Blend to the exit position
            *pAbsOrigin = Lerp( flSplineFrac, vecAbsOrigin, vecEyeExitEndpoint );

            if ( pFOV != NULL )
            {
                if ( pData->flFOV > flDefaultFOV )
                {
                    *pFOV = Lerp( flFracFOV, pData->flFOV, flDefaultFOV );
                }
            }
        }
        else
        {
            // Blend from our starting position to the desired origin
            *pAbsOrigin = Lerp( flSplineFrac, pData->vecOriginSaved, vecAbsOrigin );

            if ( pFOV != NULL )
            {
                if ( pData->flFOV > flDefaultFOV )
                {
                    *pFOV = Lerp( flFracFOV, flDefaultFOV, pData->flFOV );
                }
            }
        }
    }
    else if ( pFOV != NULL )
    {
        if ( pData->flFOV > flDefaultFOV )
        {
            // Not running an entry/exit anim. Just use the vehicle's FOV.
            *pFOV = pData->flFOV;
        }
    }
}
Exemplo n.º 4
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
CFourWheelVehiclePhysics *CFourWheelServerVehicle::GetFourWheelVehiclePhysics( void )
{
	CPropVehicleDriveable *pVehicle = GetFourWheelVehicle();
	return pVehicle->GetPhysics();
}
Exemplo n.º 5
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : &info - 
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
void CNPC_CombineS::Event_Killed( const CTakeDamageInfo &info )
{
	// Don't bother if we've been told not to, or the player has a megaphyscannon
	if ( combine_spawn_health.GetBool() == false || PlayerHasMegaPhysCannon() )
	{
		BaseClass::Event_Killed( info );
		return;
	}

	CBasePlayer *pPlayer = ToBasePlayer( info.GetAttacker() );

	if ( !pPlayer )
	{
		CPropVehicleDriveable *pVehicle = dynamic_cast<CPropVehicleDriveable *>( info.GetAttacker() ) ;
		if ( pVehicle && pVehicle->GetDriver() && pVehicle->GetDriver()->IsPlayer() )
		{
			pPlayer = assert_cast<CBasePlayer *>( pVehicle->GetDriver() );
		}
	}

	if ( pPlayer != NULL )
	{
		// Elites drop alt-fire ammo, so long as they weren't killed by dissolving.
		if( IsElite() )
		{
#ifdef HL2_EPISODIC
			if ( HasSpawnFlags( SF_COMBINE_NO_AR2DROP ) == false )
#endif
			{
				CBaseEntity *pItem = DropItem( "item_ammo_ar2_altfire", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) );

				if ( pItem )
				{
					IPhysicsObject *pObj = pItem->VPhysicsGetObject();

					if ( pObj )
					{
						Vector			vel		= RandomVector( -64.0f, 64.0f );
						AngularImpulse	angImp	= RandomAngularImpulse( -300.0f, 300.0f );

						vel[2] = 0.0f;
						pObj->AddVelocity( &vel, &angImp );
					}

					if( info.GetDamageType() & DMG_DISSOLVE )
					{
						CBaseAnimating *pAnimating = dynamic_cast<CBaseAnimating*>(pItem);

						if( pAnimating )
						{
							pAnimating->Dissolve( NULL, gpGlobals->curtime, false, ENTITY_DISSOLVE_NORMAL );
						}
					}
					else
					{
						WeaponManager_AddManaged( pItem );
					}
				}
			}
		}

		CHalfLife2 *pHL2GameRules = static_cast<CHalfLife2 *>(g_pGameRules);

		// Attempt to drop health
		if ( pHL2GameRules->NPC_ShouldDropHealth( pPlayer ) )
		{
			DropItem( "item_healthvial", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) );
			pHL2GameRules->NPC_DroppedHealth();
		}
		
		if ( HasSpawnFlags( SF_COMBINE_NO_GRENADEDROP ) == false )
		{
			// Attempt to drop a grenade
			if ( pHL2GameRules->NPC_ShouldDropGrenade( pPlayer ) )
			{
				DropItem( "weapon_frag", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) );
				pHL2GameRules->NPC_DroppedGrenade();
			}
		}
	}

	BaseClass::Event_Killed( info );
}
Exemplo n.º 6
0
void CHLPlayerMove::FinishMove( CBasePlayer *player, CUserCmd *ucmd, CMoveData *move )
{
	// Call the default FinishMove code.
	BaseClass::FinishMove( player, ucmd, move );
	if ( gpGlobals->frametime != 0 )
	{		
		float distance = 0.0f;
		IServerVehicle *pVehicle = player->GetVehicle();
		if ( pVehicle )
		{
			pVehicle->FinishMove( player, ucmd, move );
			IPhysicsObject *obj = player->GetVehicleEntity()->VPhysicsGetObject();
			if ( obj )
			{
				Vector newPos;
				obj->GetPosition( &newPos, NULL );
				distance = VectorLength( newPos - m_vecSaveOrigin );
				if ( m_vecSaveOrigin == vec3_origin || distance > 100.0f )
					distance = 0.0f;
				m_vecSaveOrigin = newPos;
			}
			
			CPropVehicleDriveable *driveable = dynamic_cast< CPropVehicleDriveable * >( player->GetVehicleEntity() );
			if ( driveable )
			{
				// Overturned and at rest (if still moving it can fix itself)
				bool bFlipped = driveable->IsOverturned() && ( distance < 0.5f );
				if ( m_bVehicleFlipped != bFlipped )
				{
					if ( bFlipped )
					{
						gamestats->Event_FlippedVehicle( player, driveable );
					}
					m_bVehicleFlipped = bFlipped;
				}
			}
			else
			{
				m_bVehicleFlipped = false;
			}
		}
		else
		{
			m_bVehicleFlipped = false;
			distance = VectorLength( player->GetAbsOrigin() - m_vecSaveOrigin );
		}
		if ( distance > 0 )
		{
			gamestats->Event_PlayerTraveled( player, distance, pVehicle ? true : false, !pVehicle && static_cast< CHL2_Player * >( player )->IsSprinting() );
		}
	}

	bool bGodMode = ( player->GetFlags() & FL_GODMODE ) ? true : false;
	if ( m_bInGodMode != bGodMode )
	{
		m_bInGodMode = bGodMode;
		if ( bGodMode )
		{
			gamestats->Event_PlayerEnteredGodMode( player );
		}
	}
	bool bNoClip = ( player->GetMoveType() == MOVETYPE_NOCLIP );
	if ( m_bInNoClip != bNoClip )
	{
		m_bInNoClip = bNoClip;
		if ( bNoClip )
		{
			gamestats->Event_PlayerEnteredNoClip( player );
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : &info - 
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
void CNPC_CombineS::Event_Killed( const CTakeDamageInfo &info )
{
	if (!(g_Language.GetInt() == LANGUAGE_GERMAN || UTIL_IsLowViolence()) && info.GetDamageType() & (DMG_BLAST | DMG_CRUSH) && !(info.GetDamageType() & (DMG_DISSOLVE)) && !PlayerHasMegaPhysCannon())
	{
		Vector vecDamageDir = info.GetDamageForce();
		SpawnBlood(GetAbsOrigin(), g_vecAttackDir, BloodColor(), info.GetDamage());
		DispatchParticleEffect("headshotspray", GetAbsOrigin(), GetAbsAngles(), this);
		EmitSound("Gore.Headshot");
		float flFadeTime = 25.0;

		CGib::SpawnSpecificGibs(this, 1, 750, 1500, "models/gibs/soldier_head.mdl", flFadeTime);
		
		Vector vecRagForce;
		vecRagForce.x = random->RandomFloat(-400, 400);
		vecRagForce.y = random->RandomFloat(-400, 400);
		vecRagForce.z = random->RandomFloat(0, 250);

		Vector vecRagDmgForce = (vecRagForce + vecDamageDir);

		CBaseEntity *pLeftArmGib = CreateRagGib("models/gibs/soldier_left_arm.mdl", GetAbsOrigin(), GetAbsAngles(), vecRagDmgForce, flFadeTime, IsOnFire());
		if (pLeftArmGib)
		{ 
			color32 color = pLeftArmGib->GetRenderColor();
			pLeftArmGib->SetRenderColor(color.r, color.g, color.b, color.a);
		}

		CBaseEntity *pRightArmGib = CreateRagGib("models/gibs/soldier_right_arm.mdl", GetAbsOrigin(), GetAbsAngles(), vecRagDmgForce, flFadeTime, IsOnFire());
		if (pRightArmGib)
		{
			color32 color = pRightArmGib->GetRenderColor();
			pRightArmGib->SetRenderColor(color.r, color.g, color.b, color.a);
		}

		CBaseEntity *pTorsoGib = CreateRagGib("models/gibs/soldier_torso.mdl", GetAbsOrigin(), GetAbsAngles(), vecRagDmgForce, flFadeTime, IsOnFire());
		if (pTorsoGib)
		{
			color32 color = pTorsoGib->GetRenderColor();
			pTorsoGib->SetRenderColor(color.r, color.g, color.b, color.a);
		}

		CBaseEntity *pPelvisGib = CreateRagGib("models/gibs/soldier_pelvis.mdl", GetAbsOrigin(), GetAbsAngles(), vecRagDmgForce, flFadeTime, IsOnFire());
		if (pPelvisGib)
		{
			color32 color = pPelvisGib->GetRenderColor();
			pPelvisGib->SetRenderColor(color.r, color.g, color.b, color.a);
		}

		CBaseEntity *pLeftLegGib = CreateRagGib("models/gibs/soldier_left_leg.mdl", GetAbsOrigin(), GetAbsAngles(), vecRagDmgForce, flFadeTime, IsOnFire());
		if (pLeftLegGib)
		{
			color32 color = pLeftLegGib->GetRenderColor();
			pLeftLegGib->SetRenderColor(color.r, color.g, color.b, color.a);
		}

		CBaseEntity *pRightLegGib = CreateRagGib("models/gibs/soldier_right_leg.mdl", GetAbsOrigin(), GetAbsAngles(), vecRagDmgForce, flFadeTime, IsOnFire());
		if (pRightLegGib)
		{
			color32 color = pRightLegGib->GetRenderColor();
			pRightLegGib->SetRenderColor(color.r, color.g, color.b, color.a);
		}

		//now add smaller gibs.
		CGib::SpawnSpecificGibs(this, 3, 750, 1500, "models/gibs/pgib_p3.mdl", flFadeTime);
		CGib::SpawnSpecificGibs(this, 3, 750, 1500, "models/gibs/pgib_p4.mdl", flFadeTime);

		Vector forceVector = CalcDamageForceVector(info);

		// Drop any weapon that I own
		if (VPhysicsGetObject())
		{
			Vector weaponForce = forceVector * VPhysicsGetObject()->GetInvMass();
			Weapon_Drop(m_hActiveWeapon, NULL, &weaponForce);
		}
		else
		{
			Weapon_Drop(m_hActiveWeapon);
		}

		if (info.GetAttacker()->IsPlayer())
		{
			((CSingleplayRules*)GameRules())->NPCKilled(this, info);
		}

		UTIL_Remove(this);
		SetThink(NULL);
		return;
	}

	// Don't bother if we've been told not to, or the player has a megaphyscannon
	if ( combine_spawn_health.GetBool() == false || PlayerHasMegaPhysCannon() )
	{
		BaseClass::Event_Killed( info );
		return;
	}

	CBasePlayer *pPlayer = ToBasePlayer( info.GetAttacker() );

	if ( !pPlayer )
	{
		CPropVehicleDriveable *pVehicle = dynamic_cast<CPropVehicleDriveable *>( info.GetAttacker() ) ;
		if ( pVehicle && pVehicle->GetDriver() && pVehicle->GetDriver()->IsPlayer() )
		{
			pPlayer = assert_cast<CBasePlayer *>( pVehicle->GetDriver() );
		}
	}

	if ( pPlayer != NULL )
	{
		CHalfLife2 *pHL2GameRules = static_cast<CHalfLife2 *>(g_pGameRules);

		// Attempt to drop health
		if ( pHL2GameRules->NPC_ShouldDropHealth( pPlayer ) )
		{
			DropItem( "item_healthvial", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) );
			pHL2GameRules->NPC_DroppedHealth();
		}
		
		if ( HasSpawnFlags( SF_COMBINE_NO_GRENADEDROP ) == false )
		{
			// Attempt to drop a grenade
			if ( pHL2GameRules->NPC_ShouldDropGrenade( pPlayer ) )
			{
				DropItem( "weapon_frag", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) );
				pHL2GameRules->NPC_DroppedGrenade();
			}
		}
	}

	BaseClass::Event_Killed( info );
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : &info - 
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
void CNPC_CombineAce::Event_Killed( const CTakeDamageInfo &info )
{
	if (!(g_Language.GetInt() == LANGUAGE_GERMAN || UTIL_IsLowViolence()) && info.GetDamageType() & (DMG_BLAST | DMG_CRUSH) && !(info.GetDamageType() & (DMG_DISSOLVE)) && !PlayerHasMegaPhysCannon())
	{
		Vector vecDamageDir = info.GetDamageForce();
		SpawnBlood(GetAbsOrigin(), g_vecAttackDir, BloodColor(), info.GetDamage());
		DispatchParticleEffect("headshotspray", GetAbsOrigin(), GetAbsAngles(), this);
		EmitSound("Gore.Headshot");
		float flFadeTime = 25.0;

		CGib::SpawnSpecificGibs(this, 1, 750, 1500, "models/gibs/soldier_ace_head.mdl", flFadeTime);

		Vector vecRagForce;
		vecRagForce.x = random->RandomFloat(-400, 400);
		vecRagForce.y = random->RandomFloat(-400, 400);
		vecRagForce.z = random->RandomFloat(0, 250);

		Vector vecRagDmgForce = (vecRagForce + vecDamageDir);

		CBaseEntity *pLeftArmGib = CreateRagGib("models/gibs/soldier_ace_left_arm.mdl", GetAbsOrigin(), GetAbsAngles(), vecRagDmgForce, flFadeTime, IsOnFire());
		if (pLeftArmGib)
		{
			color32 color = pLeftArmGib->GetRenderColor();
			pLeftArmGib->SetRenderColor(color.r, color.g, color.b, color.a);
		}

		CBaseEntity *pRightArmGib = CreateRagGib("models/gibs/soldier_ace_right_arm.mdl", GetAbsOrigin(), GetAbsAngles(), vecRagDmgForce, flFadeTime, IsOnFire());
		if (pRightArmGib)
		{
			color32 color = pRightArmGib->GetRenderColor();
			pRightArmGib->SetRenderColor(color.r, color.g, color.b, color.a);
		}

		CBaseEntity *pTorsoGib = CreateRagGib("models/gibs/soldier_ace_torso.mdl", GetAbsOrigin(), GetAbsAngles(), vecRagDmgForce, flFadeTime, IsOnFire());
		if (pTorsoGib)
		{
			color32 color = pTorsoGib->GetRenderColor();
			pTorsoGib->SetRenderColor(color.r, color.g, color.b, color.a);
		}

		CBaseEntity *pPelvisGib = CreateRagGib("models/gibs/soldier_ace_pelvis.mdl", GetAbsOrigin(), GetAbsAngles(), vecRagDmgForce, flFadeTime, IsOnFire());
		if (pPelvisGib)
		{
			color32 color = pPelvisGib->GetRenderColor();
			pPelvisGib->SetRenderColor(color.r, color.g, color.b, color.a);
		}

		CBaseEntity *pLeftLegGib = CreateRagGib("models/gibs/soldier_ace_left_leg.mdl", GetAbsOrigin(), GetAbsAngles(), vecRagDmgForce, flFadeTime, IsOnFire());
		if (pLeftLegGib)
		{
			color32 color = pLeftLegGib->GetRenderColor();
			pLeftLegGib->SetRenderColor(color.r, color.g, color.b, color.a);
		}

		CBaseEntity *pRightLegGib = CreateRagGib("models/gibs/soldier_ace_right_leg.mdl", GetAbsOrigin(), GetAbsAngles(), vecRagDmgForce, flFadeTime, IsOnFire());
		if (pRightLegGib)
		{
			color32 color = pRightLegGib->GetRenderColor();
			pRightLegGib->SetRenderColor(color.r, color.g, color.b, color.a);
		}

		//now add smaller gibs.
		CGib::SpawnSpecificGibs(this, 3, 750, 1500, "models/gibs/pgib_p3.mdl", flFadeTime);
		CGib::SpawnSpecificGibs(this, 3, 750, 1500, "models/gibs/pgib_p4.mdl", flFadeTime);

		if (!m_bNoArmor && combine_ace_shieldspawnmode.GetInt() > 0)
		{
			pArmor->Remove();
			DropItem("item_shield", WorldSpaceCenter() + RandomVector(-4, 4), RandomAngle(0, 360));
		}

		Vector forceVector = CalcDamageForceVector(info);

		// Drop any weapon that I own
		if (VPhysicsGetObject())
		{
			Vector weaponForce = forceVector * VPhysicsGetObject()->GetInvMass();
			Weapon_Drop(m_hActiveWeapon, NULL, &weaponForce);
		}
		else
		{
			Weapon_Drop(m_hActiveWeapon);
		}

		if (info.GetAttacker()->IsPlayer())
		{
			((CSingleplayRules*)GameRules())->NPCKilled(this, info);
		}

		UTIL_Remove(this);
		SetThink(NULL);
		return;
	}

	// Don't bother if we've been told not to, or the player has a megaphyscannon
	if ( combine_ace_spawn_health.GetBool() == false || PlayerHasMegaPhysCannon() )
	{
		BaseClass::Event_Killed( info );
		return;
	}

	SetEyeState(ACE_EYE_DEAD);

	if (!m_bNoArmor && combine_ace_shieldspawnmode.GetInt() > 0)
	{
		pArmor->Remove();
	}

	CBasePlayer *pPlayer = ToBasePlayer( info.GetAttacker() );

	if ( !pPlayer )
	{
		CPropVehicleDriveable *pVehicle = dynamic_cast<CPropVehicleDriveable *>( info.GetAttacker() ) ;
		if ( pVehicle && pVehicle->GetDriver() && pVehicle->GetDriver()->IsPlayer() )
		{
			pPlayer = assert_cast<CBasePlayer *>( pVehicle->GetDriver() );
		}
	}

	if ( pPlayer != NULL )
	{
		// Elites drop alt-fire ammo, so long as they weren't killed by dissolving.
#ifdef HL2_EPISODIC
		if (HasSpawnFlags(SF_COMBINE_NO_AR2DROP) == false)
#endif
		{
			if (FClassnameIs(GetActiveWeapon(), "weapon_ar2"))
			{
				CBaseEntity *pItem = DropItem("item_ammo_ar2_altfire", WorldSpaceCenter() + RandomVector(-4, 4), RandomAngle(0, 360));

				if (pItem)
				{
					IPhysicsObject *pObj = pItem->VPhysicsGetObject();

					if (pObj)
					{
						Vector			vel = RandomVector(-64.0f, 64.0f);
						AngularImpulse	angImp = RandomAngularImpulse(-300.0f, 300.0f);

						vel[2] = 0.0f;
						pObj->AddVelocity(&vel, &angImp);
					}

					if (info.GetDamageType() & DMG_DISSOLVE)
					{
						CBaseAnimating *pAnimating = dynamic_cast<CBaseAnimating*>(pItem);

						if (pAnimating)
						{
							pAnimating->Dissolve(NULL, gpGlobals->curtime, false, ENTITY_DISSOLVE_NORMAL);
						}
					}
					else
					{
						WeaponManager_AddManaged(pItem);
					}
				}
			}
			else if (FClassnameIs(GetActiveWeapon(), "weapon_smg1"))
			{
				CBaseEntity *pItem = DropItem("item_ammo_smg1_grenade", WorldSpaceCenter() + RandomVector(-4, 4), RandomAngle(0, 360));

				if (pItem)
				{
					IPhysicsObject *pObj = pItem->VPhysicsGetObject();

					if (pObj)
					{
						Vector			vel = RandomVector(-64.0f, 64.0f);
						AngularImpulse	angImp = RandomAngularImpulse(-300.0f, 300.0f);

						vel[2] = 0.0f;
						pObj->AddVelocity(&vel, &angImp);
					}

					if (info.GetDamageType() & DMG_DISSOLVE)
					{
						CBaseAnimating *pAnimating = dynamic_cast<CBaseAnimating*>(pItem);

						if (pAnimating)
						{
							pAnimating->Dissolve(NULL, gpGlobals->curtime, false, ENTITY_DISSOLVE_NORMAL);
						}
					}
					else
					{
						WeaponManager_AddManaged(pItem);
					}
				}
			}
		}

		CHalfLife2 *pHL2GameRules = static_cast<CHalfLife2 *>(g_pGameRules);

		// Attempt to drop health
		if ( pHL2GameRules->NPC_ShouldDropHealth( pPlayer ) )
		{
			DropItem( "item_healthvial", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) );
			pHL2GameRules->NPC_DroppedHealth();
		}

		if (!m_bNoArmor && combine_ace_shieldspawnmode.GetInt() > 0)
		{
			DropItem("item_shield", WorldSpaceCenter() + RandomVector(-4, 4), RandomAngle(0, 360));
		}
	}

	BaseClass::Event_Killed( info );
}