//========================================================= // IdleHello // Try to greet player first time he's seen //========================================================= int CAI_PlayerAlly::FIdleHello( void ) { if (!IsOkToSpeak()) return false; // if this is first time scientist has seen player, greet him if (!GetExpresser()->SpokeConcept(TLK_HELLO)) { // get a player CBaseEntity *pPlayer = FindNearestFriend(true); if (pPlayer) { if (FInViewCone(pPlayer) && FVisible(pPlayer)) { SetSpeechTarget( pPlayer ); Speak( TLK_HELLO ); return true; } } } return false; }
void CNPCSimpleTalker::OnStartingFollow( CBaseEntity *pTarget ) { GetExpresser()->SetSpokeConcept( TLK_HELLO, NULL ); // Don't say hi after you've started following if ( IsOkToSpeak() ) // don't speak if idle talk is blocked. player commanded/use follow will always speak Speak( TLK_STARTFOLLOW ); SetSpeechTarget( GetTarget() ); ClearCondition( COND_PLAYER_PUSHING ); }
// try to smell something void CNPCSimpleTalker::TrySmellTalk( void ) { if ( !IsOkToSpeak() ) return; if ( HasCondition( COND_SMELL ) && GetExpresser()->CanSpeakConcept( TLK_SMELL ) ) Speak( TLK_SMELL ); }
// try to smell something void CAI_PlayerAlly::TrySmellTalk( void ) { if ( !IsOkToSpeak() ) return; if ( HasCondition( COND_SMELL ) && GetExpresser()->CanSpeakConcept( TLK_SMELL ) ) Speak( TLK_SMELL ); }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Purpose: Respond to a previous question //----------------------------------------------------------------------------- void CNPCSimpleTalker::IdleRespond( void ) { if (!IsOkToSpeak()) return; // play response SpeakAnswerFriend( GetSpeechTarget() ); DeferAllIdleSpeech( random->RandomFloat( TALKER_DEFER_IDLE_SPEAK_MIN, TALKER_DEFER_IDLE_SPEAK_MAX ) ); }
//========================================================= // FIdleStare //========================================================= int CAI_PlayerAlly::FIdleStare( void ) { if (!IsOkToSpeak()) return false; Speak( TLK_STARE ); SetSpeechTarget( FindNearestFriend( true ) ); return true; }
//========================================================= // ALertSound - barney says "Freeze!" //========================================================= void CNPC_HL1Barney::AlertSound( void ) { if ( GetEnemy() != NULL ) { if ( IsOkToSpeak() ) { Speak( BA_ATTACK ); } } }
//----------------------------------------------------------------------------- // Purpose: // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool CNPCSimpleTalker::CanSayHello( void ) { #ifndef HL1_DLL if ( Classify() == CLASS_PLAYER_ALLY_VITAL ) return false; #endif if ( GetSpeechFilter() && GetSpeechFilter()->NeverSayHello() ) return false; if ( !GetExpresser()->CanSpeakConcept(TLK_HELLO) || GetExpresser()->SpokeConcept(TLK_HELLO) ) return false; if ( !IsOkToSpeak() ) return false; return true; }
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; }
int CNPC_Monk::SelectSchedule() { if( HasCondition( COND_HEAR_DANGER ) ) { SpeakIfAllowed( TLK_DANGER ); return SCHED_TAKE_COVER_FROM_BEST_SOUND; } if ( HasCondition( COND_TALKER_PLAYER_DEAD ) && !m_bMournedPlayer && IsOkToSpeak() ) { m_bMournedPlayer = true; Speak( TLK_IDLE ); } if( !BehaviorSelectSchedule() ) { if ( HasCondition ( COND_NO_PRIMARY_AMMO ) ) { return SCHED_HIDE_AND_RELOAD; } } return BaseClass::SelectSchedule(); }
//========================================================= // SelectSchedule - Decides which type of schedule best suits // the monster's current state and conditions. Then calls // monster's member function to get a pointer to a schedule // of the proper type. //========================================================= int CNPC_HL1Barney::SelectSchedule( void ) { if ( m_NPCState == NPC_STATE_COMBAT || GetEnemy() != NULL ) { // Priority action! if (!m_fGunDrawn ) return SCHED_ARM_WEAPON; } if ( GetFollowTarget() == NULL ) { if ( HasCondition( COND_PLAYER_PUSHING ) && !(GetSpawnFlags() & SF_NPC_PREDISASTER ) ) // Player wants me to move return SCHED_HL1TALKER_FOLLOW_MOVE_AWAY; } if ( BehaviorSelectSchedule() ) return BaseClass::SelectSchedule(); if ( HasCondition( COND_HEAR_DANGER ) ) { CSound *pSound; pSound = GetBestSound(); ASSERT( pSound != NULL ); if ( pSound && pSound->IsSoundType( SOUND_DANGER ) ) return SCHED_TAKE_COVER_FROM_BEST_SOUND; } if ( HasCondition( COND_ENEMY_DEAD ) && IsOkToSpeak() ) { Speak( BA_KILL ); } switch( m_NPCState ) { case NPC_STATE_COMBAT: { // dead enemy if ( HasCondition( COND_ENEMY_DEAD ) ) return BaseClass::SelectSchedule(); // call base class, all code to handle dead enemies is centralized there. // always act surprized with a new enemy if ( HasCondition( COND_NEW_ENEMY ) && HasCondition( COND_LIGHT_DAMAGE) ) return SCHED_SMALL_FLINCH; if ( HasCondition( COND_HEAVY_DAMAGE ) ) return SCHED_TAKE_COVER_FROM_ENEMY; if ( !HasCondition(COND_SEE_ENEMY) ) { // we can't see the enemy if ( !HasCondition(COND_ENEMY_OCCLUDED) ) { // enemy is unseen, but not occluded! // turn to face enemy return SCHED_COMBAT_FACE; } else { return SCHED_CHASE_ENEMY; } } } break; case NPC_STATE_ALERT: case NPC_STATE_IDLE: if ( HasCondition( COND_LIGHT_DAMAGE ) || HasCondition( COND_HEAVY_DAMAGE ) ) { // flinch if hurt return SCHED_SMALL_FLINCH; } if ( GetEnemy() == NULL && GetFollowTarget() ) { if ( !GetFollowTarget()->IsAlive() ) { // UNDONE: Comment about the recently dead player here? StopFollowing(); break; } else { return SCHED_TARGET_FACE; } } // try to say something about smells TrySmellTalk(); break; } return BaseClass::SelectSchedule(); }
//========================================================= // FIdleSpeak // ask question of nearby friend, or make statement //========================================================= int CNPCSimpleTalker::FIdleSpeak( void ) { // try to start a conversation, or make statement int pitch; if (!IsOkToSpeak()) return false; Assert( GetExpresser()->SemaphoreIsAvailable( this ) ); 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)) { Speak( TLK_PLHURT3 ); return true; } else if (GetExpresser()->CanSpeakConcept( TLK_PLHURT2) && (GetTarget()->m_iHealth <= GetTarget()->m_iMaxHealth / 4)) { Speak( TLK_PLHURT2 ); return true; } else if (GetExpresser()->CanSpeakConcept( TLK_PLHURT1) && (GetTarget()->m_iHealth <= GetTarget()->m_iMaxHealth / 2)) { 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 } } } // ROBIN: Disabled idle question & answer for now /* // if there is a friend nearby to speak to, play sentence, set friend's response time, return CBaseEntity *pFriend = FindNearestFriend(false); // 75% chance of talking to another citizen if one is available. if (pFriend && !(pFriend->IsMoving()) && random->RandomInt( 0, 3 ) != 0 ) { if ( SpeakQuestionFriend( pFriend ) ) { // force friend to answer CAI_PlayerAlly *pTalkNPC = dynamic_cast<CAI_PlayerAlly *>(pFriend); if (pTalkNPC && !pTalkNPC->HasSpawnFlags(SF_NPC_GAG) && !pTalkNPC->IsInAScript() ) { SetSpeechTarget( pFriend ); pTalkNPC->SetAnswerQuestion( this ); pTalkNPC->GetExpresser()->BlockSpeechUntil( GetExpresser()->GetTimeSpeechComplete() ); m_nSpeak++; } // Don't let anyone else butt in. DeferAllIdleSpeech( random->RandomFloat( TALKER_DEFER_IDLE_SPEAK_MIN, TALKER_DEFER_IDLE_SPEAK_MAX ), pTalkNPC ); return true; } } */ // Otherwise, play an idle statement, try to face client when making a statement. CBaseEntity *pFriend = FindNearestFriend(true); if ( pFriend ) { SetSpeechTarget( pFriend ); // If we're about to talk to the player, and we've never said hello, say hello first if ( !GetSpeechFilter() || !GetSpeechFilter()->NeverSayHello() ) { if ( GetExpresser()->CanSpeakConcept( TLK_HELLO ) && !GetExpresser()->SpokeConcept( TLK_HELLO ) ) { SayHelloToPlayer( pFriend ); return true; } } if ( Speak( TLK_IDLE ) ) { DeferAllIdleSpeech( random->RandomFloat( TALKER_DEFER_IDLE_SPEAK_MIN, TALKER_DEFER_IDLE_SPEAK_MAX ) ); m_nSpeak++; } else { // We failed to speak. Don't try again for a bit. m_flNextIdleSpeechTime = gpGlobals->curtime + 3; } return true; } // didn't speak m_flNextIdleSpeechTime = gpGlobals->curtime + 3; return false; }
int CAI_PlayerAlly::TranslateSchedule( int scheduleType ) { switch( scheduleType ) { case SCHED_TARGET_FACE: // speak during 'use' if (random->RandomInt(0,99) < 2) //Msg("target chase speak\n" ); return SCHED_TALKER_IDLE_SPEAK_WAIT; // If we're hurt, look for a healthkit if ( m_flLastHealthKitSearch < gpGlobals->curtime && GetHealth() <= GetMaxHealth() / 2 ) return SCHED_TALKER_LOOK_FOR_HEALTHKIT; break; case SCHED_ALERT_STAND: // If we're hurt, look for a healthkit if ( m_flLastHealthKitSearch < gpGlobals->curtime && GetHealth() <= GetMaxHealth() / 2 ) return SCHED_TALKER_LOOK_FOR_HEALTHKIT; break; case SCHED_IDLE_STAND: { // if never seen player, try to greet him if (GetExpresser()->CanSpeakConcept( TLK_HELLO) && !GetExpresser()->SpokeConcept(TLK_HELLO)) { return SCHED_TALKER_IDLE_HELLO; } // If we're hurt, look for a healthkit if ( m_flLastHealthKitSearch < gpGlobals->curtime && GetHealth() <= GetMaxHealth() / 2 ) return SCHED_TALKER_LOOK_FOR_HEALTHKIT; // sustained light wounds? if (GetExpresser()->CanSpeakConcept( TLK_WOUND) && !GetExpresser()->SpokeConcept(TLK_WOUND) && (m_iHealth <= (m_iMaxHealth * 0.75))) { Speak( TLK_WOUND ); return SCHED_IDLE_STAND; } // sustained heavy wounds? else if (GetExpresser()->CanSpeakConcept( TLK_MORTAL) && (m_iHealth <= (m_iMaxHealth * 0.5))) { Speak( TLK_MORTAL ); return SCHED_IDLE_STAND; } // talk about world if (IsOkToSpeak() && random->RandomInt(0,m_nSpeak * 2) == 0) { //Msg("standing idle speak\n" ); return SCHED_TALKER_IDLE_SPEAK; } if ( !GetExpresser()->IsSpeaking() && HasCondition ( COND_SEE_PLAYER ) && random->RandomInt( 0, 6 ) == 0 ) { CBasePlayer *pPlayer = (CBasePlayer *)CBaseEntity::Instance( engine->PEntityOfEntIndex( 1 ) ); Assert( pPlayer ); if ( pPlayer ) { // watch the client. Vector forward; AngleVectors( pPlayer->GetLocalAngles(), &forward ); if ( ( pPlayer->GetLocalOrigin() - GetLocalOrigin() ).Length2D() < TLK_STARE_DIST && UTIL_DotPoints( pPlayer->GetLocalOrigin(), GetLocalOrigin(), 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 { if (GetExpresser()->IsSpeaking()) // look at who we're talking to return SCHED_TALKER_IDLE_EYE_CONTACT; else // regular standing idle return SCHED_IDLE_STAND; } } break; case SCHED_CHASE_ENEMY_FAILED: { int baseType = BaseClass::TranslateSchedule(scheduleType); if ( baseType != SCHED_CHASE_ENEMY_FAILED ) return baseType; return SCHED_TAKE_COVER_FROM_ENEMY; } break; } return BaseClass::TranslateSchedule( scheduleType ); }
//========================================================= // 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; }
bool CAI_PlayerAlly::CanPlaySentence( bool fDisregardState ) { if ( fDisregardState ) return BaseClass::CanPlaySentence( fDisregardState ); return IsOkToSpeak(); }