Пример #1
0
//-----------------------------------------------------------------------------
// Purpose: Activate any nearby bugbait targets
//			Returns true if the bugbait target wants to suppress the call.
//-----------------------------------------------------------------------------
bool CGrenadeBugBait::ActivateBugbaitTargets( CBaseEntity *pOwner, Vector vecOrigin, bool bSqueezed )
{
	//Attempt to activate any spawners in a radius around the bugbait
	CBaseEntity*	pList[100];
	Vector			delta( bugbait_grenade_radius.GetFloat(), bugbait_grenade_radius.GetFloat(), bugbait_grenade_radius.GetFloat() );
	bool			suppressCall = false;

	int count = UTIL_EntitiesInBox( pList, 100, vecOrigin - delta, vecOrigin + delta, 0 );
	
	// If the bugbait's been thrown, look for nearby targets to affect
	if ( !bSqueezed )
	{
		for ( int i = 0; i < count; i++ )
		{
			// If close enough, make combine soldiers freak out when hit
			if ( UTIL_DistApprox( pList[i]->WorldSpaceCenter(), vecOrigin ) < bugbait_grenade_radius.GetFloat() )
			{
				// Must be a soldier
				if ( FClassnameIs( pList[i], "npc_combine_s") )
				{
					CAI_BaseNPC *pCombine = pList[i]->MyNPCPointer();

					if ( pCombine != NULL )
					{
						trace_t tr;
						UTIL_TraceLine( vecOrigin, pCombine->EyePosition(), MASK_ALL, pOwner, COLLISION_GROUP_NONE, &tr);

						if ( tr.fraction == 1.0 || tr.m_pEnt == pCombine )
						{
							// Randomize the start time a little so multiple combine hit by 
							// the same bugbait don't all dance in synch.
							g_EventQueue.AddEvent( pCombine, "HitByBugbait", RandomFloat(0, 0.5), pOwner, pOwner );
						}
					}
				}
			}
		}
	}
	// Iterate over all sensors to see if they detected this impact
	for ( CBugBaitSensor *pSensor = GetBugBaitSensorList(); pSensor != NULL; pSensor = pSensor->m_pNext )
	{
		if ( pSensor == NULL )
			continue;

		if ( pSensor->IsDisabled() )
			continue;

		if ( bSqueezed && pSensor->DetectsSqueeze() == false )
			continue;

		if ( !bSqueezed && pSensor->DetectsThrown() == false )
			continue;

		//Make sure we're within range of the sensor
		if ( pSensor->GetRadius() > ( pSensor->GetAbsOrigin() - vecOrigin ).Length() )
		{
			//Tell the sensor it's been hit
			if ( pSensor->Baited( pOwner ) )
			{
				//If we're suppressing the call to antlions, then don't make a bugbait sound
				if ( pSensor->SuppressCall() )
				{
					suppressCall = true;
				}
			}
		}
	}

	return suppressCall;
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CGrenadeBugBait::BugBaitTouch( CBaseEntity *pOther )
{
	Assert( pOther );
	if ( !pOther->IsSolid() )
		return;

	if ( m_pSporeTrail != NULL )
	{
		m_pSporeTrail->m_bEmit = false;
	}

	//Do effect for the hit
	SporeExplosion *pSporeExplosion = SporeExplosion::CreateSporeExplosion();

	if ( pSporeExplosion )
	{
		Vector	dir = -GetAbsVelocity();
		VectorNormalize( dir );

		QAngle	angles;
		VectorAngles( dir, angles );

		pSporeExplosion->SetLocalAngles( angles );
		pSporeExplosion->SetLocalOrigin( GetAbsOrigin() );
		pSporeExplosion->m_flSpawnRate			= 1.0f;
		pSporeExplosion->m_flParticleLifetime	= 2.0f;
		pSporeExplosion->SetRenderColor( 0.0f, 0.5f, 0.25f, 0.15f );

		pSporeExplosion->m_flStartSize			= 0.0f;
		pSporeExplosion->m_flEndSize			= 32.0f;
		pSporeExplosion->m_flSpawnRadius		= 2.0f;

		pSporeExplosion->SetLifetime( bugbait_distract_time.GetFloat() );
		
		UTIL_Relink( pSporeExplosion );
	}

	trace_t	tr;
	Vector	traceDir, tracePos;

	Vector	directions[ NUM_SPLASHES ] =
	{
		Vector(  1,  0,  0 ),
		Vector( -1,  0,  0 ),
		Vector(  0,  1,  0 ),
		Vector(  0, -1,  0 ),
		Vector(  0,  0,  1 ),
		Vector(  0,  0, -1 ),
	};

	//Splatter decals everywhere
	for ( int i = 0; i < NUM_SPLASHES; i++ )
	{
		traceDir = directions[i];
		tracePos = GetAbsOrigin() + ( traceDir * 64.0f );

		UTIL_TraceLine( GetAbsOrigin(), tracePos, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr );

		if ( tr.fraction < 1.0f )
		{
			UTIL_DecalTrace( &tr, "BeerSplash" );	//TODO: Use real decal
		}
	}

	//Make a splat sound
	CPASAttenuationFilter filter( this );
	EmitSound( filter, entindex(), CHAN_WEAPON, "weapons/bugbait/splat.wav", 1.0f, ATTN_NORM );

	//Attempt to activate any spawners in a radius around the bugbait
	CBaseEntity*	pList[100];
	Vector			delta( 256, 256, 256 );
	bool			suppressCall = false;

	int count = UTIL_EntitiesInBox( pList, 100, GetAbsOrigin() - delta, GetAbsOrigin() + delta, 0 );
	
	//Iterate over all the possible targets
	for ( i = 0; i < count; i++ )
	{
		//See if this is a bugbait sensor
		if ( FClassnameIs( pList[i], "point_bugbait" ) )
		{
			CBugBaitSensor *pSensor = dynamic_cast<CBugBaitSensor *>(pList[i]);

			if ( pSensor == NULL )
				continue;

			//Make sure we're within range of the sensor
			if ( pSensor->GetRadius() > ( pSensor->GetAbsOrigin() - GetAbsOrigin() ).Length() )
			{
				//Tell the sensor it's been hit
				pSensor->Baited( GetOwner() );

				//If we're suppressing the call to antlions, then don't make a bugbait sound
				if ( pSensor->SuppressCall() )
				{
					suppressCall = true;
				}
			}
		}
	}

	//Make sure we want to call antlions
	if ( suppressCall == false )
	{
		//Alert any antlions around
		CSoundEnt::InsertSound( SOUND_BUGBAIT, GetAbsOrigin(), bugbait_hear_radius.GetInt(), bugbait_distract_time.GetFloat(), GetOwner() );
	}

	//Go away
	UTIL_Remove( this );
}