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