Exemplo n.º 1
0
void CWeaponDrainGrenade::Explode( CBaseCombatCharacter* pAttacker,
						   CBaseEntity* pInflictor,
						   CBaseEntity* pIgnore,
						   Vector vecPosition,
						   float flDamage,
						   float flRadius,
						   float flDrainFocus )
{

#if !defined( CLIENT_DLL )
	//CSoundEnt::InsertSound ( SOUND_COMBAT, vecPosition, 1024, 3.0 );
	
	CTakeDamageInfo info;
	info.CFSet( pInflictor, pAttacker, vec3_origin, vecPosition, flDamage, DMG_BLAST, WEAPON_NONE, &vecPosition, false );
	info.SetDrainFocus( flDrainFocus );

	DispatchParticleEffect("grenade_explosion", vecPosition, vec3_angle, pIgnore);

	//TODO: Figure out sound.
	CPASAttenuationFilter filter( this );
	filter.UsePredictionRules();
	EmitSound( filter, entindex(), "Numen.FireAoE" );
	//CSoundEnt::InsertSound ( SOUND_COMBAT, GetAbsOrigin(), BASEGRENADE_EXPLOSION_VOLUME, 3.0 );
	
	RadiusDamage( info, vecPosition, flRadius );

#endif //!defined( CLIENT_DLL )
}
Exemplo n.º 2
0
void CWeaponDrainGrenade::RadiusDamage( const CTakeDamageInfo &inputInfo, const Vector &vecSrcIn, float flRadius )
{
	CTakeDamageInfo info = inputInfo;

	CBaseEntity *pEntity = NULL;
	trace_t		tr;
	float		flAdjustedDamage, falloff;
	Vector		vecSpot;
	Vector		vecToTarget;
	Vector		vecEndPos;

	Vector vecSrc = vecSrcIn;

	if ( flRadius )
		falloff = info.GetDamage() / flRadius;
	else
		falloff = 1.0;

	int bInWater = (UTIL_PointContents ( vecSrc ) & MASK_WATER) ? true : false;
	
	vecSrc.z += 1;// in case grenade is lying on the ground

	// iterate on all entities in the vicinity.
	for ( CEntitySphereQuery sphere( vecSrc, flRadius ); ( pEntity = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() )
	{
		if (!pEntity || !ToCFPlayer(pEntity))
			continue;

		// Don't drain teammates.
		if (CFGameRules()->PlayerRelationship(GetThrower(), pEntity) == GR_TEAMMATE && ToCFPlayer(pEntity) != ToCFPlayer(GetThrower()))
			continue;

		if ( !pEntity->IsAlive() )
			continue;

		if ( pEntity->m_takedamage != DAMAGE_NO )
		{

			// blast's don't tavel into or out of water
			if (bInWater && pEntity->GetWaterLevel() == 0)
				continue;
			if (!bInWater && pEntity->GetWaterLevel() == 3)
				continue;

			// radius damage can only be blocked by the world
			vecSpot = pEntity->BodyTarget( vecSrc );

			bool bHit = false;

			UTIL_TraceLine( vecSrc, vecSpot, MASK_SOLID_BRUSHONLY, info.GetInflictor(), COLLISION_GROUP_NONE, &tr );

			if (tr.startsolid)
			{
				// if we're stuck inside them, fixup the position and distance
				tr.endpos = vecSrc;
				tr.fraction = 0.0;
			}

			vecEndPos = tr.endpos;

			if( tr.fraction == 1.0 || tr.m_pEnt == pEntity )
			{
				bHit = true;
			}

			if ( bHit )
			{
				// the explosion can 'see' this entity, so hurt them!
				vecToTarget = ( vecEndPos - vecSrc );

				// decrease damage for an ent that's farther from the blast's center.
				flAdjustedDamage = vecToTarget.Length() * falloff;
				flAdjustedDamage = info.GetDrainFocus() - flAdjustedDamage;

				if ( flAdjustedDamage > 0 )
				{
					CTakeDamageInfo adjustedInfo = info;
					adjustedInfo.SetDrainFocus( flAdjustedDamage );

					Vector dir = vecToTarget;
					VectorNormalize( dir );

					// If we don't have a damage force, manufacture one
					if ( adjustedInfo.GetDamagePosition() == vec3_origin || adjustedInfo.GetDamageForce() == vec3_origin )
					{
						CalculateExplosiveDamageForce( &adjustedInfo, dir, vecSrc, 1.5	/* explosion scale! */ );
					}
					else
					{
						// Assume the force passed in is the maximum force. Decay it based on falloff.
						float flForce = adjustedInfo.GetDamageForce().Length() * falloff;
						adjustedInfo.SetDamageForce( dir * flForce );
						adjustedInfo.SetDamagePosition( vecSrc );
					}

					float flFocusDrained = adjustedInfo.GetDrainFocus();

					float& flFocus = ToCFPlayer(pEntity)->m_pStats->m_flFocus.GetForModify();
					if (flFocus > cf_minfocusdrain.GetFloat())
						flFocus -= flFocusDrained;
					if (flFocus < cf_minfocusdrain.GetFloat())
						flFocus = cf_minfocusdrain.GetFloat();

					CEffectData	data;

					data.m_nHitBox = GetParticleSystemIndex( "grenade_drained" );
					data.m_vOrigin = ToCFPlayer(pEntity)->GetCentroid();
					data.m_vStart = vecSrc;
					data.m_vAngles = QAngle(0,0,0);

					data.m_nEntIndex = pEntity->entindex();
					data.m_fFlags |= PARTICLE_DISPATCH_FROM_ENTITY;
					data.m_nDamageType = PATTACH_CUSTOMORIGIN;

					DispatchEffect( "ParticleEffect", data );

					// Now hit all triggers along the way that respond to damage... 
					pEntity->TraceAttackToTriggers( adjustedInfo, vecSrc, vecEndPos, dir );
				}
			}
		}
	}
}