Exemplo n.º 1
0
//---------------------------------------------------------
// Purpose: Applies the desired relationships to an entity
//---------------------------------------------------------
void CAI_Relationship::ApplyRelationship( CBaseEntity *pActivator, CBaseEntity *pCaller )
{
	// @TODO (toml 10-22-04): sort out MP relationships 
	
	// The player spawns slightly after the NPCs, meaning that if we don't wait, the
	// player will miss any relationships placed on them.
	#ifdef SecobMod__Enable_Fixed_Multiplayer_AI
		if ( UTIL_GetLocalPlayer() ) 
		{
			SetThink( &CAI_Relationship::ApplyRelationshipThink );
			SetNextThink( gpGlobals->curtime );
		}
	#else
		if ( AI_IsSinglePlayer() && !UTIL_GetLocalPlayer() )
		{
			SetThink( &CAI_Relationship::ApplyRelationshipThink );
			SetNextThink( gpGlobals->curtime );
		}
	#endif //SecobMod__Enable_Fixed_Multiplayer_AI

	if ( !m_bIsActive )
	{
		SetActive( true );
	}

	ChangeRelationships( m_iDisposition, NOT_REVERTING, pActivator, pCaller );
}
Exemplo n.º 2
0
void CNPCSimpleTalker::RunTask( const Task_t *pTask )
{
	switch( pTask->iTask )
	{
	case TASK_TALKER_WAIT_FOR_SEMAPHORE:
		if ( GetExpresser()->SemaphoreIsAvailable( this ) )
			TaskComplete();
		break;

	case TASK_TALKER_CLIENT_STARE:
	case TASK_TALKER_LOOK_AT_CLIENT:

		if ( pTask->iTask == TASK_TALKER_CLIENT_STARE && AI_IsSinglePlayer() )
		{
			// Get edict for one player
			CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
			Assert( pPlayer );

			// fail out if the player looks away or moves away.
			if ( ( pPlayer->GetAbsOrigin() - GetAbsOrigin() ).Length2D() > TALKER_STARE_DIST )
			{
				// player moved away.
				TaskFail("Player moved away");
			}

			Vector forward;
			AngleVectors( pPlayer->GetLocalAngles(), &forward );
			if ( UTIL_DotPoints( pPlayer->GetAbsOrigin(), GetAbsOrigin(), forward ) < m_flFieldOfView )
			{
				// player looked away
				TaskFail("Player looked away");
			}
		}

		if ( IsWaitFinished() )
		{
			TaskComplete();
		}
		break;

	case TASK_TALKER_EYECONTACT:
		if (IsMoving() || !GetExpresser()->IsSpeaking() || GetSpeechTarget() == NULL)
		{
			TaskComplete();
		}
		break;

	case TASK_WAIT_FOR_MOVEMENT:
		FIdleSpeakWhileMoving();
		BaseClass::RunTask( pTask );
		break;

	default:
		BaseClass::RunTask( pTask );
	}
}
Exemplo n.º 3
0
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CAI_AllyManager::CountAllies( int *pTotal, int *pMedics )
{
	(*pTotal) = (*pMedics) = 0;

	if ( !AI_IsSinglePlayer() )
	{
		// @TODO (toml 10-22-04): no MP support right now
		return;
	}

	const Vector &	vPlayerPos = UTIL_GetLocalPlayer()->GetAbsOrigin();
	CAI_BaseNPC **	ppAIs 	= g_AI_Manager.AccessAIs();
	int 			nAIs 	= g_AI_Manager.NumAIs();

	for ( int i = 0; i < nAIs; i++ )
	{
		if ( ppAIs[i]->IsAlive() && ppAIs[i]->IsPlayerAlly() )
		{
			// Vital allies do not count.
			if( ppAIs[i]->Classify() == CLASS_PLAYER_ALLY_VITAL )
				continue;

			// They only count if I can use them.
			if( ppAIs[i]->HasSpawnFlags(SF_CITIZEN_NOT_COMMANDABLE) )
				continue;
			
			// They only count if I can use them.
			if( ppAIs[i]->IRelationType( UTIL_GetLocalPlayer() ) != D_LI )
				continue;

			// Skip distant NPCs
			if ( !ppAIs[i]->IsInPlayerSquad() && 
				!UTIL_FindClientInPVS( ppAIs[i]->edict() ) && 
				( ( ppAIs[i]->GetAbsOrigin() - vPlayerPos ).LengthSqr() > 150*12 ||
				  fabsf( ppAIs[i]->GetAbsOrigin().z - vPlayerPos.z ) > 192 ) )
				continue;

			if( FClassnameIs( ppAIs[i], "npc_citizen" ) ) 
			{  
				CNPC_Citizen *pCitizen = assert_cast<CNPC_Citizen *>(ppAIs[i]);
				if ( !pCitizen->CanJoinPlayerSquad() )
					continue;

				if ( pCitizen->WasInPlayerSquad() && !pCitizen->IsInPlayerSquad() )
					continue;

				if ( ppAIs[i]->HasSpawnFlags( SF_CITIZEN_MEDIC ) )
					(*pMedics)++;
			}

			(*pTotal)++;
		}
	}
}
Exemplo n.º 4
0
bool CGib::SUB_AllowedToFade( void )
{
	if( VPhysicsGetObject() )
	{
		if( VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD || GetEFlags() & EFL_IS_BEING_LIFTED_BY_BARNACLE )
			return false;
	}

	CBasePlayer *pPlayer = ( AI_IsSinglePlayer() ) ? UTIL_GetLocalPlayer() : NULL;

	if ( pPlayer && pPlayer->FInViewCone( this ) && m_bForceRemove == false )
	{
		return false;
	}

	return true;
}
Exemplo n.º 5
0
void CAI_LeadBehavior::LeadPlayer( const AI_LeadArgs_t &leadArgs, CAI_LeadBehaviorHandler *pSink )
{
	CAI_PlayerAlly *pOuter = dynamic_cast<CAI_PlayerAlly*>(GetOuter());
	if ( pOuter && AI_IsSinglePlayer() )
	{
		pOuter->SetSpeechTarget( UTIL_GetLocalPlayer() );
	}

	if( SetGoal( leadArgs ) )
	{
		SetCondition( COND_PROVOKED );
		Connect( pSink );
		NotifyChangeBehaviorStatus();
	}
	else
	{
		DevMsg( "*** Warning! LeadPlayer() has a NULL Goal Ent\n" );
	}
}
Exemplo n.º 6
0
int CNPCSimpleTalker::SelectNonCombatSpeechSchedule()
{
	if ( !IsOkToSpeak() )
		return SCHED_NONE;
		
	// talk about world
	if ( ShouldSpeakRandom( m_nSpeak * 2, GetSpeechFilter() ? GetSpeechFilter()->GetIdleModifier() : 1.0 ) )
	{
		//Msg("standing idle speak\n" );
		return SCHED_TALKER_IDLE_SPEAK;
	}
	
	// failed to speak, so look at the player if he's around
	if ( AI_IsSinglePlayer() && GetExpresser()->CanSpeak() && HasCondition ( COND_SEE_PLAYER ) && random->RandomInt( 0, 6 ) == 0 )
	{
		CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
		Assert( pPlayer );

		if ( pPlayer )
		{
			// watch the client.
			Vector forward;
			AngleVectors( pPlayer->GetLocalAngles(), &forward );
			if ( ( pPlayer->GetAbsOrigin() - GetAbsOrigin() ).Length2D() < TALKER_STARE_DIST	&& 
				 UTIL_DotPoints( pPlayer->GetAbsOrigin(), GetAbsOrigin(), forward ) >= m_flFieldOfView )
			{
				// go into the special STARE schedule if the player is close, and looking at me too.
				return SCHED_TALKER_IDLE_WATCH_CLIENT_STARE;
			}

			return SCHED_TALKER_IDLE_WATCH_CLIENT;
		}
	}
	else
	{
		// look at who we're talking to
		if ( GetSpeechTarget() && GetExpresser()->IsSpeaking() )
			return SCHED_TALKER_IDLE_EYE_CONTACT;
	}
	return SCHED_NONE;
}
Exemplo n.º 7
0
//------------------------------------------------------------------------------
// Purpose :
// Input   :
// Output  :
//------------------------------------------------------------------------------
void CNPC_EnemyFinder::StartNPC ( void )
{
	AddSpawnFlags(SF_NPC_FALL_TO_GROUND);	// this prevents CAI_BaseNPC from slamming the finder to 
											// the ground just because it's not MOVETYPE_FLY
	BaseClass::StartNPC();

	if ( AI_IsSinglePlayer() && m_PlayerFreePass.GetParams().duration > 0.1 )
	{
		m_PlayerFreePass.SetPassTarget( UTIL_PlayerByIndex(1) );

		AI_FreePassParams_t freePassParams = m_PlayerFreePass.GetParams();

		freePassParams.coverDist = 120;
		freePassParams.peekEyeDist = 1.75;
		freePassParams.peekEyeDistZ = 4;

		m_PlayerFreePass.SetParams( freePassParams );
	}

	if (!m_nStartOn)
	{
		SetThink(NULL);
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CNPCEventResponseSystem::FrameUpdatePreEntityThink()
{
 	if ( !m_ActiveEvents.Count() || !AI_IsSinglePlayer() || !UTIL_GetLocalPlayer() )
		return;

	if ( m_flNextEventPoll > gpGlobals->curtime )
		return;
	m_flNextEventPoll = gpGlobals->curtime + 0.2;

	// Move through all events, removing expired ones and finding NPCs for active ones.
	for ( int i = m_ActiveEvents.First(); i != m_ActiveEvents.InvalidIndex(); )
	{	
 		float flTime = m_ActiveEvents[i].flEventTime;
		const char *pResponse = m_ActiveEvents.GetElementName(i);

		// Save off the next index so we can safely remove this one
		int iNext = m_ActiveEvents.Next(i); 

		// Should it have expired by now?
		if ( !m_ActiveEvents[i].bPreventExpiration && (flTime + NPCEVENTRESPONSE_GIVEUP_TIME) < gpGlobals->curtime )
		{
			if ( ai_debug_eventresponses.GetBool() ) 
			{
				Msg( "NPCEVENTRESPONSE: (%.2f) Removing expired event named: %s\n", gpGlobals->curtime, pResponse );
			}

			m_ActiveEvents.RemoveAt(i);
		}
		else if ( m_ActiveEvents[i].flNextResponseTime < gpGlobals->curtime )
		{
			// If we've fired once, and our current event should expire now, then expire.
			if ( m_ActiveEvents[i].bPreventExpiration && (flTime + NPCEVENTRESPONSE_GIVEUP_TIME) < gpGlobals->curtime )
			{
				if ( ai_debug_eventresponses.GetBool() ) 
				{
					Msg( "NPCEVENTRESPONSE: (%.2f) Removing expired fired event named: %s\n", gpGlobals->curtime, pResponse );
				}

				m_ActiveEvents.RemoveAt(i);
			}
			else
			{
				float flNearestDist = NPCEVENTRESPONSE_DISTANCE_SQR;
				CAI_BaseNPC *pNearestNPC = NULL;
				Vector vecPlayerCenter = UTIL_GetLocalPlayer()->WorldSpaceCenter();

				// Try and find the nearest NPC to the player
				CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs();
				for ( int j = 0; j < g_AI_Manager.NumAIs(); j++ )
				{
					if ( ppAIs[j]->CanRespondToEvent( pResponse ))
					{
						float flDistToPlayer = ( vecPlayerCenter - ppAIs[j]->WorldSpaceCenter()).LengthSqr();
						if ( flDistToPlayer < flNearestDist )
						{
							flNearestDist = flDistToPlayer;
							pNearestNPC = ppAIs[j];
						}
					}
				}

				// Found one? 
				if ( pNearestNPC )
				{
					if ( pNearestNPC->RespondedTo( pResponse, m_ActiveEvents[i].bForce, m_ActiveEvents[i].bCancelScript ) )
					{
						// Don't remove the response yet. Leave it around until the refire time has expired.
						// This stops repeated firings of the same concept from spamming the NPCs.
						m_ActiveEvents[i].bPreventExpiration = true;
						m_ActiveEvents[i].flNextResponseTime = gpGlobals->curtime + NPCEVENTRESPONSE_REFIRE_TIME;

						if ( ai_debug_eventresponses.GetBool() ) 
						{
							Msg( "NPCEVENTRESPONSE: (%.2f) Event '%s' responded to by NPC '%s'. Refire available at: %.2f\n", gpGlobals->curtime, pResponse, pNearestNPC->GetDebugName(), m_ActiveEvents[i].flNextResponseTime );
						}

						// Don't issue multiple responses at once
						return;
					}
				}
			}
		}

		i = iNext;
	}
}
//-----------------------------------------------------------------------------
// 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 );
		}
	}
}