Example #1
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CGrenadeHopwire::KillStriders( void )
{
	CBaseEntity *pEnts[128];
	Vector	mins, maxs;

	ClearBounds( mins, maxs );
	AddPointToBounds( -Vector( MAX_STRIDER_STUN_DISTANCE_HORZ, MAX_STRIDER_STUN_DISTANCE_HORZ, MAX_STRIDER_STUN_DISTANCE_HORZ ), mins, maxs );
	AddPointToBounds(  Vector( MAX_STRIDER_STUN_DISTANCE_HORZ, MAX_STRIDER_STUN_DISTANCE_HORZ, MAX_STRIDER_STUN_DISTANCE_HORZ ), mins, maxs );
	AddPointToBounds( -Vector( MAX_STRIDER_STUN_DISTANCE_VERT, MAX_STRIDER_STUN_DISTANCE_VERT, MAX_STRIDER_STUN_DISTANCE_VERT ), mins, maxs );
	AddPointToBounds(  Vector( MAX_STRIDER_STUN_DISTANCE_VERT, MAX_STRIDER_STUN_DISTANCE_VERT, MAX_STRIDER_STUN_DISTANCE_VERT ), mins, maxs );

	// FIXME: It's probably much faster to simply iterate over the striders in the map, rather than any entity in the radius - jdw

	// Find any striders in range of us
	int numTargets = UTIL_EntitiesInBox( pEnts, ARRAYSIZE( pEnts ), GetAbsOrigin()+mins, GetAbsOrigin()+maxs, FL_NPC );
	float targetDistHorz, targetDistVert;

	for ( int i = 0; i < numTargets; i++ )
	{
		// Only affect striders
		if ( FClassnameIs( pEnts[i], "npc_strider" ) == false )
			continue;

		// We categorize our spatial relation to the strider in horizontal and vertical terms, so that we can specify both parameters separately
		targetDistHorz = UTIL_DistApprox2D( pEnts[i]->GetAbsOrigin(), GetAbsOrigin() );
		targetDistVert = fabs( pEnts[i]->GetAbsOrigin()[2] - GetAbsOrigin()[2] );

		if ( targetDistHorz < MAX_STRIDER_KILL_DISTANCE_HORZ && targetDistHorz < MAX_STRIDER_KILL_DISTANCE_VERT )
		{
			// Kill the strider
			float fracDamage = ( pEnts[i]->GetMaxHealth() / hopwire_strider_hits.GetFloat() ) + 1.0f;
			CTakeDamageInfo killInfo( this, this, fracDamage, DMG_GENERIC );
			Vector	killDir = pEnts[i]->GetAbsOrigin() - GetAbsOrigin();
			VectorNormalize( killDir );

			killInfo.SetDamageForce( killDir * -1000.0f );
			killInfo.SetDamagePosition( GetAbsOrigin() );

			pEnts[i]->TakeDamage( killInfo );
		}
		else if ( targetDistHorz < MAX_STRIDER_STUN_DISTANCE_HORZ && targetDistHorz < MAX_STRIDER_STUN_DISTANCE_VERT )
		{
			// Stun the strider
			CTakeDamageInfo killInfo( this, this, 200.0f, DMG_GENERIC );
			pEnts[i]->TakeDamage( killInfo );
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *pTask - 
//-----------------------------------------------------------------------------
void CAI_PolicingBehavior::StartTask( const Task_t *pTask )
{
	switch (pTask->iTask)
	{
	case TASK_POLICE_GET_PATH_TO_HARASS_GOAL:
		{
			Vector	harassDir = ( m_hPoliceGoal->GetTarget()->WorldSpaceCenter() - WorldSpaceCenter() );
			float	flDist = VectorNormalize( harassDir );

			// See if we're already close enough
			if ( flDist < pTask->flTaskData )
			{
				TaskComplete();
				break;
			}

			float	flInter1, flInter2;
			Vector	harassPos = GetAbsOrigin() + ( harassDir * ( flDist - pTask->flTaskData ) );

			// Find a point on our policing radius to stand on
			if ( IntersectInfiniteRayWithSphere( GetAbsOrigin(), harassDir, m_hPoliceGoal->GetAbsOrigin(), m_hPoliceGoal->GetRadius(), &flInter1, &flInter2 ) )
			{
				Vector vPos = m_hPoliceGoal->GetAbsOrigin() + harassDir * ( MAX( flInter1, flInter2 ) );

				// See how far away the default one is
				float testDist = UTIL_DistApprox2D( m_hPoliceGoal->GetAbsOrigin(), harassPos );
				
				// If our other goal is closer, choose it
				if ( testDist > UTIL_DistApprox2D( m_hPoliceGoal->GetAbsOrigin(), vPos ) )
				{
					harassPos = vPos;
				}
			}

			if ( GetNavigator()->SetGoal( harassPos, (int)pTask->flTaskData ) )
			{
				GetNavigator()->SetMovementActivity( (Activity) ACT_WALK_ANGRY );
				GetNavigator()->SetArrivalDirection( m_hPoliceGoal->GetTarget() );
				TaskComplete();
			}
			else
			{
				TaskFail( FAIL_NO_ROUTE );
			}
		}
		break;
	
	case TASK_POLICE_GET_PATH_TO_POLICE_GOAL:
		{
			if ( GetNavigator()->SetGoal( m_hPoliceGoal->GetAbsOrigin(), (int)pTask->flTaskData ) )
			{
				GetNavigator()->SetArrivalDirection( m_hPoliceGoal->GetAbsAngles() );
				TaskComplete();
			}
			else
			{
				TaskFail( FAIL_NO_ROUTE );
			}
		}
		break;

	case TASK_POLICE_ANNOUNCE_HARASS:
		{
			AnnouncePolicing();

			// Randomly say this again in the future
			m_flNextHarassTime = gpGlobals->curtime + random->RandomInt( 4, 6 );

			// Scatter rubber-neckers
			CSoundEnt::InsertSound( SOUND_MOVE_AWAY, GetAbsOrigin(), 256, 2.0f, GetOuter() );
		}
		TaskComplete();
		break;

	case TASK_POLICE_FACE_ALONG_GOAL:
		{
			// We may have lost our police goal in the 2 seconds we wait before this task
			if ( m_hPoliceGoal )
			{
				GetMotor()->SetIdealYaw( m_hPoliceGoal->GetAbsAngles().y );
				GetOuter()->SetTurnActivity(); 
			}
		}
		break;

	default:
		BaseClass::StartTask( pTask );
		break;
	}
}
bool CNPC_Dog::FindPhysicsObject( const char *pPickupName, CBaseEntity *pIgnore )
{
	CBaseEntity		*pEnt = NULL;
	CBaseEntity		*pNearest = NULL;
	float			flDist;
	IPhysicsObject	*pPhysObj = NULL;
	float			flNearestDist = 99999;

	if ( pPickupName != NULL && strlen( pPickupName ) > 0 )
	{
		pEnt = gEntList.FindEntityByName( NULL, pPickupName );
		
		if ( m_hUnreachableObjects.Find( pEnt ) == -1  )
		{
			m_bHasObject = false;
			m_hPhysicsEnt = pEnt;
			return true;
		}
	}
	
	while ( ( pEnt = gEntList.FindEntityByClassname( pEnt, "prop_physics" ) ) != NULL )
	{
		//We don't want this one.
		if ( pEnt == pIgnore )
			 continue;

		if ( m_hUnreachableObjects.Find( pEnt ) != -1 )
			 continue;

		pPhysObj = pEnt->VPhysicsGetObject();

		if( pPhysObj == NULL )
			continue;

		if ( pPhysObj->GetMass() > DOG_MAX_THROW_MASS )
			 continue;
		
		Vector center = pEnt->WorldSpaceCenter();
		flDist = UTIL_DistApprox2D( GetAbsOrigin(), center );

		vcollide_t *pCollide = modelinfo->GetVCollide( pEnt->GetModelIndex() );

		if ( pCollide == NULL )
			 continue;

		if ( pPhysObj->GetGameFlags() & FVPHYSICS_PLAYER_HELD )
			 continue;

		if ( pPhysObj->IsMoveable() == false )
			 continue;

		if ( pEnt->GetCollisionGroup() == COLLISION_GROUP_DEBRIS || 
			 pEnt->GetCollisionGroup() == COLLISION_GROUP_INTERACTIVE_DEBRIS )
			 continue;

		if ( center.z > EyePosition().z )
			 continue;

		if ( flDist >= flNearestDist )
			 continue;

		if ( FVisible( pEnt ) == false )
			 continue;
		
		pNearest = pEnt;
		flNearestDist = flDist;
	}

	m_bHasObject = false;
	m_hPhysicsEnt = pNearest;

	if ( dog_debug.GetBool() == true )
	{
		if ( pNearest )
			 NDebugOverlay::Box( pNearest->WorldSpaceCenter(), pNearest->CollisionProp()->OBBMins(), pNearest->CollisionProp()->OBBMaxs(), 255, 0, 255, true, 3 );
	}

	if( m_hPhysicsEnt == NULL )
	{
		return false;
	}
	else
	{
		return true;
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CAI_BehaviorAlyxInjured::GatherConditions( void )
{
	BaseClass::GatherConditions();

	// Always stomp over this
	ClearCondition( COND_INJURED_TOO_FAR_FROM_PLAYER );
	ClearCondition( COND_INJURED_OVERWHELMED );

	// See if we're overwhelmed by foes
	if ( NumKnownEnemiesInRadius( GetOuter()->GetAbsOrigin(), COVER_DISTANCE ) >= MIN_ENEMY_MOB )
	{
		SetCondition( COND_INJURED_OVERWHELMED );
	}

	// Determines whether we consider ourselves in danger
	bool bInDanger = (  HasCondition( COND_LIGHT_DAMAGE ) || 
						HasCondition( COND_HEAVY_DAMAGE ) || 
						HasCondition( COND_INJURED_OVERWHELMED ) );

	// See if we're too far away from the player and in danger
	if ( AI_IsSinglePlayer() && bInDanger )
	{
		bool bWarnPlayer = false;

		// This only works in single-player
		CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 );
		if ( pPlayer != NULL )
		{
			// FIXME: This distance may need to be the length of the shortest walked path between the follower and the target

			// Get our approximate distance to the player
			float flDistToPlayer = UTIL_DistApprox2D( GetOuter()->GetAbsOrigin(), pPlayer->GetAbsOrigin() );
			if ( flDistToPlayer > injured_help_plee_range.GetFloat() )
			{
				bWarnPlayer = true;
			}
			else if ( flDistToPlayer > (injured_help_plee_range.GetFloat()*0.5f) && HasCondition( COND_SEE_PLAYER ) == false )
			{
				// Cut our distance in half if we can't see the player
				bWarnPlayer = true;
			}
		}

		// Yell for help!
		if ( bWarnPlayer )
		{
			// FIXME: This should be routed through the normal speaking code with a system to emit from the player's suit.
			
			CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 );
			//float flPlayerDistSqr = ( GetOuter()->GetAbsOrigin() - pPlayer->GetAbsOrigin() ).LengthSqr();

			// If the player is too far away or we can't see him
			//if ( HasCondition( COND_SEE_PLAYER ) == false || flPlayerDistSqr > Square( 128 ) )
			{
				if ( m_flNextWarnTime < gpGlobals->curtime )
				{
					pPlayer->EmitSound( "npc_alyx.injured_too_far" );
					m_flNextWarnTime = gpGlobals->curtime + random->RandomFloat( 3.0f, 5.0f );
				}
			}
			/*
			else
			{
				SpeakIfAllowed( TLK_INJURED_FOLLOW_TOO_FAR );
				m_flNextWarnTime = gpGlobals->curtime + random->RandomFloat( 3.0f, 5.0f );
			}
			*/

			SetCondition( COND_INJURED_TOO_FAR_FROM_PLAYER );
		}
	}
}