//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *pEntity - 
//-----------------------------------------------------------------------------
void CAI_SpeechFilter::OnEntityCreated( CBaseEntity *pEntity )
{
	if ( !m_bDisabled && ( pEntity->NameMatches( m_iszSubject ) || pEntity->ClassMatches( m_iszSubject ) ) )
	{
#ifndef CSTRIKE_DLL
		CAI_PlayerAlly *pAlly = dynamic_cast<CAI_PlayerAlly *>(pEntity);
		if ( pAlly )
		{
			pAlly->SetSpeechFilter( this );
		}
		else if ( pEntity->IsNPC() )
		{
			DevWarning("ai_speechfilter %s tries to use %s as a subject, but it's not a talking NPC.\n", STRING(GetEntityName()), STRING(pEntity->GetEntityName()) );
		}
#endif
	}
}
bool CAI_LeadBehavior::Speak( AIConcept_t concept )
{
	CAI_Expresser *pExpresser = GetOuter()->GetExpresser();
	if ( !pExpresser )
		return false;

	// If the leader is gagged, don't speak any lead speech
	if ( m_gagleader )
		return false;

	// If we haven't said the start speech, don't nag
	bool bNag = ( FStrEq(concept,TLK_LEAD_COMINGBACK) || FStrEq(concept, TLK_LEAD_CATCHUP) || FStrEq(concept, TLK_LEAD_RETRIEVE) );
	if ( !m_hasspokenstart && bNag )
		return false;

	if ( hl2_episodic.GetBool() )
	{
		// If we're a player ally, only speak the concept if we're allowed to.
		// This allows the response rules to control it better (i.e. handles respeakdelay)
		// We ignore nag timers for this, because the response rules will control refire rates.
		CAI_PlayerAlly *pAlly = dynamic_cast<CAI_PlayerAlly*>(GetOuter());
		if ( pAlly )
 			return pAlly->SpeakIfAllowed( concept, GetConceptModifiers( concept ) );
	}

	// Don't spam Nags
	if ( bNag )
	{
		if ( m_flSpeakNextNagTime > gpGlobals->curtime )
		{
			DevMsg( GetOuter(), "Leader didn't speak due to Nag timer.\n");
			return false;
		}
	}
	
	if ( pExpresser->Speak( concept, GetConceptModifiers( concept ) ) )
	{
		m_flSpeakNextNagTime = gpGlobals->curtime + LEAD_NAG_TIME;
		return true;
	}

	return false;
}
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" );
	}
}
void CAI_PlayerAlly::AlertFriends( CBaseEntity *pKiller )
{
	CBaseEntity *pFriend = NULL;
	int i;

	// for each friend in this bsp...
	for ( i = 0; i < TLK_CFRIENDS; i++ )
	{
		while (pFriend = EnumFriends( pFriend, i, true ))
		{
			CAI_BaseNPC *pNPC = pFriend->MyNPCPointer();
			if ( pNPC->IsAlive() )
			{
				// If a client killed me, make everyone else mad/afraid of him
				if ( pKiller->GetFlags() & FL_CLIENT )
				{
					pNPC->SetSchedule( SCHED_TALKER_BETRAYED );
#ifdef ALLIES_CAN_BE_PROVOKED
					pNPC->Remember( bits_MEMORY_PROVOKED );

					if( IsSelected() )
					{
						PlayerSelect( false );
					}
#endif
				}
				else
				{
					if( IRelationType(pKiller) == D_HT)
					{
						// Killed by an enemy!!!
						CAI_PlayerAlly *pAlly = (CAI_PlayerAlly *)pNPC;
						
						if( pAlly && pAlly->GetExpresser()->CanSpeakConcept( TLK_ALLY_KILLED ) )
						{
							pAlly->Speak( TLK_ALLY_KILLED );
						}
					}
				}
			}
		}
	}
}
Example #5
0
//-----------------------------------------------------------------------------
// Purpose: Say hello to the specified player
//-----------------------------------------------------------------------------
void CNPCSimpleTalker::SayHelloToPlayer( CBaseEntity *pPlayer )
{
	Assert( !GetExpresser()->SpokeConcept(TLK_HELLO) );

	SetSpeechTarget( pPlayer );

	Speak( TLK_HELLO );
	DeferAllIdleSpeech( random->RandomFloat( 5, 10 ) );

	CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs();
	CAI_PlayerAlly *pTalker;
	for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ )
	{
		pTalker = dynamic_cast<CAI_PlayerAlly *>(ppAIs[i]);

		if( pTalker && FVisible( pTalker ) )
		{
			// Tell this guy he's already said hello to the player, too.
			pTalker->GetExpresser()->SetSpokeConcept( TLK_HELLO, NULL );
		}
	}
}
//=========================================================
// FIdleSpeak
// ask question of nearby friend, or make statement
//=========================================================
int CAI_PlayerAlly::FIdleSpeak ( void )
{ 
	// try to start a conversation, or make statement
	int pitch;

	if (m_NPCState == NPC_STATE_COMBAT )
	{
		// Don't Idle Speak in combat.
		return false;
	}

	if (!IsOkToSpeak())
		return false;

	Assert( GetExpresser()->SemaphoreIsAvailable() );
	
	pitch = GetExpresser()->GetVoicePitch();
		
	// player using this entity is alive and wounded?
	CBaseEntity *pTarget = GetTarget();

	if ( pTarget != NULL )
	{
		if ( pTarget->IsPlayer() )
		{
			if ( pTarget->IsAlive() )
			{
				SetSpeechTarget( GetTarget() );
				if (GetExpresser()->CanSpeakConcept( TLK_PLHURT3) && 
					(GetTarget()->m_iHealth <= GetTarget()->m_iMaxHealth / 8))
				{
					//UTIL_EmitSoundDyn(edict(), CHAN_VOICE, m_szGrp[TLK_PLHURT3], 1.0, SNDLVL_TALKING, 0, pitch);
					Speak( TLK_PLHURT3 );
					return true;
				}
				else if (GetExpresser()->CanSpeakConcept( TLK_PLHURT2) && 
					(GetTarget()->m_iHealth <= GetTarget()->m_iMaxHealth / 4))
				{
					//UTIL_EmitSoundDyn(edict(), CHAN_VOICE, m_szGrp[TLK_PLHURT2], 1.0, SNDLVL_TALKING, 0, pitch);
					Speak( TLK_PLHURT2 );
					return true;
				}
				else if (GetExpresser()->CanSpeakConcept( TLK_PLHURT1) &&
					(GetTarget()->m_iHealth <= GetTarget()->m_iMaxHealth / 2))
				{
					//UTIL_EmitSoundDyn(edict(), CHAN_VOICE, m_szGrp[TLK_PLHURT1], 1.0, SNDLVL_TALKING, 0, pitch);
					Speak( TLK_PLHURT1 );
					return true;
				}
			}
			else
			{
				//!!!KELLY - here's a cool spot to have the talkNPC talk about the dead player if we want.
				// "Oh dear, Gordon Freeman is dead!" -Scientist
				// "Damn, I can't do this without you." -Barney
			}
		}
	}

	// if there is a friend nearby to speak to, play sentence, set friend's response time, return
	CBaseEntity *pFriend = FindNearestFriend(false);

	if (pFriend && !(pFriend->IsMoving()) && (random->RandomInt(0,99) < 60))
	{
		Speak( TLK_QUESTION );

		// force friend to answer
		CAI_PlayerAlly *pTalkNPC = dynamic_cast<CNPCSimpleTalker *>(pFriend);
		if (pTalkNPC)
		{
			SetSpeechTarget( pFriend );
			pTalkNPC->SetAnswerQuestion( this ); // UNDONE: This is EVIL!!!
			pTalkNPC->GetExpresser()->BlockSpeechUntil( GetExpresser()->GetTimeSpeechComplete() );

			m_nSpeak++;
			return true;
		}
	}

	// otherwise, play an idle statement, try to face client when making a statement.
	if ( random->RandomInt(0,1) )
	{
		//SENTENCEG_PlayRndSz( edict(), szIdleGroup, 1.0, SNDLVL_TALKING, 0, pitch );
		CBaseEntity *pFriend = FindNearestFriend(true);

		if ( pFriend )
		{
			SetSpeechTarget( pFriend );
			Speak( TLK_IDLE );
			m_nSpeak++;
			return true;
		}
	}

	// didn't speak
	GetExpresser()->BlockSpeechUntil( gpGlobals->curtime + 3 );
	return false;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CAI_SpeechFilter::PopulateSubjectList( bool purge )
{
	// Populate the subject list. Try targetname first.
	CBaseEntity *pSearch = NULL;
	int iNumSubjects = 0;
	do
	{
		pSearch = gEntList.FindEntityByName( pSearch, m_iszSubject );
		if ( pSearch )
		{
#ifndef CSTRIKE_DLL
			CAI_PlayerAlly *pAlly = dynamic_cast<CAI_PlayerAlly *>(pSearch);
			if ( pAlly )
			{
				if( purge )
				{
					pAlly->SetSpeechFilter( NULL );
				}
				else
				{
					if( pAlly->GetSpeechFilter() != NULL )
					{
						DevWarning("ai_speechfilter %s is slamming NPC %s's current speech filter.\n", STRING(GetEntityName()), STRING(pSearch->GetEntityName()) );
					}

					pAlly->SetSpeechFilter( this );
				}
			}
			else if ( pSearch->IsNPC() )
			{
				DevWarning("ai_speechfilter %s tries to use %s as a subject, but it's not a talking NPC.\n", STRING(GetEntityName()), STRING(pSearch->GetEntityName()) );
			}
#endif
			iNumSubjects++;
		}
	} while( pSearch );

	if ( !iNumSubjects )
	{
		// No subjects found by targetname! Assume classname.
		do
		{
			pSearch = gEntList.FindEntityByClassname( pSearch, STRING(m_iszSubject) );
			if( pSearch )
			{
#ifndef CSTRIKE_DLL
				CAI_PlayerAlly *pAlly = dynamic_cast<CAI_PlayerAlly *>(pSearch);
				if ( pAlly )
				{
					if( purge )
					{
						pAlly->SetSpeechFilter( NULL );
					}
					else
					{
						if( pAlly->GetSpeechFilter() != NULL )
						{
							DevWarning("ai_speechfilter %s is slamming NPC %s's current speech filter.\n", STRING(GetEntityName()), STRING(pSearch->GetEntityName()) );
						}

						pAlly->SetSpeechFilter( this );
					}
				}
				else if ( pSearch->IsNPC() )
				{
					DevWarning("ai_speechfilter %s tries to use %s as a subject, but it's not a talking NPC.\n", STRING(GetEntityName()), STRING(pSearch->GetEntityName()) );
				}
#endif
				iNumSubjects++;
			}
		} while( pSearch );
	}

	// If the subject list is still empty, we have an error!
	if ( !iNumSubjects )
	{
		DevMsg( 2, "ai_speechfilter finds no subject(s) called: %s\n", STRING( m_iszSubject ) );
	}
}