//========================================================= // 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; }
//========================================================= // IdleHello // Try to greet player first time he's seen //========================================================= bool CTalkMonster::FIdleHello() { if (!FOkToSpeak()) return false; // if this is first time scientist has seen player, greet him if (!FBitSet(m_bitsSaid, bit_saidHelloPlayer)) { // get a player CBaseEntity *pPlayer = FindNearestFriend(true); if (pPlayer) { if (FInViewCone(pPlayer) && FVisible(pPlayer)) { m_hTalkTarget = pPlayer; if ( GetSpawnFlags().Any( SF_MONSTER_PREDISASTER ) ) PlaySentence( m_szGrp[TLK_PHELLO], RANDOM_FLOAT(3, 3.5), VOL_NORM, ATTN_IDLE ); else PlaySentence( m_szGrp[TLK_HELLO], RANDOM_FLOAT(3, 3.5), VOL_NORM, ATTN_IDLE ); SetBits(m_bitsSaid, bit_saidHelloPlayer); return true; } } } return false; }
void CAI_PlayerAlly::OnChangeRunningBehavior( CAI_BehaviorBase *pOldBehavior, CAI_BehaviorBase *pNewBehavior ) { BaseClass::OnChangeRunningBehavior( pOldBehavior, pNewBehavior ); CAI_FollowBehavior *pFollowBehavior; if ( dynamic_cast<CAI_FollowBehavior *>(pNewBehavior) != NULL ) { GetExpresser()->SetSpokeConcept( TLK_HELLO, NULL ); // Don't say hi after you've started following if ( IsOkToCombatSpeak() ) Speak( TLK_USE ); SetSpeechTarget( GetTarget() ); ClearCondition( COND_PLAYER_PUSHING ); } else if ( ( pFollowBehavior = dynamic_cast<CAI_FollowBehavior *>(pOldBehavior) ) != NULL ) { if ( !(m_afMemory & bits_MEMORY_PROVOKED) ) { if ( IsOkToCombatSpeak() ) { if ( pFollowBehavior->GetFollowTarget() == NULL ) Speak( TLK_UNUSE ); else Speak( TLK_STOP ); } SetSpeechTarget( FindNearestFriend(true) ); } } }
//========================================================= // IdleHello // Try to greet player first time he's seen //========================================================= int CMTalkMonster :: FIdleHello( void ) { if (!FOkToSpeak()) return FALSE; // if this is first time scientist has seen player, greet him if (!FBitSet(m_bitsSaid, bit_saidHelloPlayer)) { // get a player edict_t *pPlayer = FindNearestFriend(TRUE); if (pPlayer) { if (UTIL_FInViewCone(pPlayer, this->edict(), m_flFieldOfView) && UTIL_FVisible(pPlayer, this->edict())) { m_hTalkTarget = pPlayer; if (FBitSet(pev->spawnflags, SF_MONSTER_PREDISASTER)) PlaySentence( m_szGrp[TLK_PHELLO], RANDOM_FLOAT(3, 3.5), VOL_NORM, ATTN_IDLE ); else PlaySentence( m_szGrp[TLK_HELLO], RANDOM_FLOAT(3, 3.5), VOL_NORM, ATTN_IDLE ); SetBits(m_bitsSaid, bit_saidHelloPlayer); return TRUE; } } } return FALSE; }
//========================================================= // FIdleStare //========================================================= bool CTalkMonster::FIdleStare() { if (!FOkToSpeak()) return false; PlaySentence( m_szGrp[TLK_STARE], RANDOM_FLOAT(5, 7.5), VOL_NORM, ATTN_IDLE ); m_hTalkTarget = FindNearestFriend( true ); return true; }
//========================================================= // FIdleStare //========================================================= int CAI_PlayerAlly::FIdleStare( void ) { if (!IsOkToSpeak()) return false; Speak( TLK_STARE ); SetSpeechTarget( FindNearestFriend( true ) ); return true; }
//========================================================= // FIdleStare //========================================================= int CMTalkMonster :: FIdleStare( void ) { if (!FOkToSpeak()) return FALSE; PlaySentence( m_szGrp[TLK_STARE], RANDOM_FLOAT(5, 7.5), VOL_NORM, ATTN_IDLE ); m_hTalkTarget = FindNearestFriend( TRUE ); return TRUE; }
//----------------------------------------------------------------------------- // Purpose: Find a nearby friend to stare at //----------------------------------------------------------------------------- int CNPCSimpleTalker::FIdleStare( void ) { // Don't idly speak if our speech filter is preventing us if ( GetSpeechFilter() && GetSpeechFilter()->GetIdleModifier() == 0 ) return true; SpeakIfAllowed( TLK_STARE ); SetSpeechTarget( FindNearestFriend( true ) ); return true; }
void CNPCSimpleTalker::OnStoppingFollow( CBaseEntity *pTarget ) { if ( !(m_afMemory & bits_MEMORY_PROVOKED) ) { if ( IsOkToCombatSpeak() ) { if ( pTarget == NULL ) Speak( TLK_STOPFOLLOW ); else Speak( TLK_STOP ); } SetSpeechTarget( FindNearestFriend(true) ); } }
int CAI_PlayerAlly::OnTakeDamage_Alive( const CTakeDamageInfo &info ) { // if player damaged this entity, have other friends talk about it. if (info.GetAttacker() && (info.GetAttacker()->GetFlags() & FL_CLIENT) && info.GetDamage() < GetHealth() ) { CBaseEntity *pFriend = FindNearestFriend(false); if (pFriend && pFriend->IsAlive()) { // only if not dead or dying! CNPCSimpleTalker *pTalkNPC = (CNPCSimpleTalker *)pFriend; pTalkNPC->SetSchedule( SCHED_TALKER_IDLE_STOP_SHOOTING ); } } return BaseClass::OnTakeDamage_Alive( info ); }
void CTalkMonster::OnTakeDamage( const CTakeDamageInfo& info ) { if ( IsAlive() ) { // if player damaged this entity, have other friends talk about it if (info.GetAttacker() && m_MonsterState != MONSTERSTATE_PRONE && info.GetAttacker()->GetFlags().Any( FL_CLIENT ) ) { CBaseEntity *pFriend = FindNearestFriend( false ); if (pFriend && pFriend->IsAlive()) { // only if not dead or dying! CTalkMonster *pTalkMonster = (CTalkMonster *)pFriend; pTalkMonster->ChangeSchedule( slIdleStopShooting ); } } } CBaseMonster::OnTakeDamage( info ); }
int CMTalkMonster :: TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType) { if ( IsAlive() ) { // if player damaged this entity, have other friends talk about it if (pevAttacker && m_MonsterState != MONSTERSTATE_PRONE && FBitSet(pevAttacker->flags, FL_CLIENT)) { edict_t *pFriend = FindNearestFriend(FALSE); if (pFriend && UTIL_IsAlive(pFriend)) { // only if not dead or dying! CMTalkMonster *pTalkMonster = (CMTalkMonster *)pFriend; pTalkMonster->ChangeSchedule( slIdleStopShooting ); } } } return CMBaseMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType); }
//========================================================= // FIdleSpeak // ask question of nearby friend, or make statement //========================================================= int CSittingScientist :: FIdleSpeak ( void ) { // try to start a conversation, or make statement int pitch; if (!FOkToSpeak()) return FALSE; // set global min delay for next conversation CTalkMonster::g_talkWaitTime = gpGlobals->time + RANDOM_FLOAT(4.8, 5.2); pitch = GetVoicePitch(); // if there is a friend nearby to speak to, play sentence, set friend's response time, return // try to talk to any standing or sitting scientists nearby CBaseEntity *pentFriend = FindNearestFriend(FALSE); if (pentFriend && RANDOM_LONG(0,1)) { CTalkMonster *pTalkMonster = GetClassPtr((CTalkMonster *)pentFriend->pev); pTalkMonster->SetAnswerQuestion( this ); IdleHeadTurn(pentFriend->pev->origin); SENTENCEG_PlayRndSz( ENT(pev), m_szGrp[TLK_PQUESTION], 1.0, ATTN_IDLE, 0, pitch ); // set global min delay for next conversation CTalkMonster::g_talkWaitTime = gpGlobals->time + RANDOM_FLOAT(4.8, 5.2); return TRUE; } // otherwise, play an idle statement if (RANDOM_LONG(0,1)) { SENTENCEG_PlayRndSz( ENT(pev), m_szGrp[TLK_PIDLE], 1.0, ATTN_IDLE, 0, pitch ); // set global min delay for next conversation CTalkMonster::g_talkWaitTime = gpGlobals->time + RANDOM_FLOAT(4.8, 5.2); return TRUE; } // never spoke CTalkMonster::g_talkWaitTime = 0; return FALSE; }
//----------------------------------------------------------------------------- // Purpose: Try to greet player first time he's seen // Output : int //----------------------------------------------------------------------------- int CNPCSimpleTalker::FIdleHello( void ) { // Filter might be preventing us from ever greeting the player if ( !CanSayHello() ) return false; // get a player CBaseEntity *pPlayer = FindNearestFriend(true); if (pPlayer) { if (FInViewCone(pPlayer) && FVisible(pPlayer)) { SayHelloToPlayer( pPlayer ); return true; } } return false; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- int CNPCSimpleTalker::OnTakeDamage_Alive( const CTakeDamageInfo &info ) { CTakeDamageInfo subInfo = info; // if player damaged this entity, have other friends talk about it. if (subInfo.GetAttacker() && (subInfo.GetAttacker()->GetFlags() & FL_CLIENT) && subInfo.GetDamage() < GetHealth() ) { CBaseEntity *pFriend = FindNearestFriend(false); if (pFriend && pFriend->IsAlive()) { // only if not dead or dying! CNPCSimpleTalker *pTalkNPC = (CNPCSimpleTalker *)pFriend; if (pTalkNPC && pTalkNPC->IsOkToCombatSpeak()) { pTalkNPC->Speak( TLK_NOSHOOT ); } } } return BaseClass::OnTakeDamage_Alive( subInfo ); }
//========================================================= // FIdleSpeak // ask question of nearby friend, or make statement //========================================================= bool CTalkMonster::FIdleSpeak() { // try to start a conversation, or make statement const char *szIdleGroup; const char *szQuestionGroup; float duration; if (!FOkToSpeak()) return false; // set idle groups based on pre/post disaster if ( GetSpawnFlags().Any( SF_MONSTER_PREDISASTER ) ) { szIdleGroup = m_szGrp[TLK_PIDLE]; szQuestionGroup = m_szGrp[TLK_PQUESTION]; // set global min delay for next conversation duration = RANDOM_FLOAT(4.8, 5.2); } else { szIdleGroup = m_szGrp[TLK_IDLE]; szQuestionGroup = m_szGrp[TLK_QUESTION]; // set global min delay for next conversation duration = RANDOM_FLOAT(2.8, 3.2); } /*int pitch = */GetVoicePitch(); // player using this entity is alive and wounded? CBaseEntity *pTarget = m_hTargetEnt; if ( pTarget != NULL ) { if ( pTarget->IsPlayer() ) { if ( pTarget->IsAlive() ) { m_hTalkTarget = m_hTargetEnt; if (!FBitSet(m_bitsSaid, bit_saidDamageHeavy) && (m_hTargetEnt->GetHealth() <= m_hTargetEnt->GetMaxHealth() / 8)) { //EMIT_SOUND_DYN( this, CHAN_VOICE, m_szGrp[TLK_PLHURT3], 1.0, ATTN_IDLE, 0, pitch); PlaySentence( m_szGrp[TLK_PLHURT3], duration, VOL_NORM, ATTN_IDLE ); SetBits(m_bitsSaid, bit_saidDamageHeavy); return true; } else if (!FBitSet(m_bitsSaid, bit_saidDamageMedium) && (m_hTargetEnt->GetHealth() <= m_hTargetEnt->GetMaxHealth() / 4)) { //EMIT_SOUND_DYN( this, CHAN_VOICE, m_szGrp[TLK_PLHURT2], 1.0, ATTN_IDLE, 0, pitch); PlaySentence( m_szGrp[TLK_PLHURT2], duration, VOL_NORM, ATTN_IDLE ); SetBits(m_bitsSaid, bit_saidDamageMedium); return true; } else if (!FBitSet(m_bitsSaid, bit_saidDamageLight) && (m_hTargetEnt->GetHealth() <= m_hTargetEnt->GetMaxHealth() / 2)) { //EMIT_SOUND_DYN( this, CHAN_VOICE, m_szGrp[TLK_PLHURT1], 1.0, ATTN_IDLE, 0, pitch); PlaySentence( m_szGrp[TLK_PLHURT1], duration, VOL_NORM, ATTN_IDLE ); SetBits(m_bitsSaid, bit_saidDamageLight); return true; } } else { //!!!KELLY - here's a cool spot to have the talkmonster 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_LONG( 0, 99 ) < 75 ) ) { PlaySentence( szQuestionGroup, duration, VOL_NORM, ATTN_IDLE ); //SENTENCEG_PlayRndSz( this, szQuestionGroup, 1.0, ATTN_IDLE, 0, pitch ); // force friend to answer CTalkMonster *pTalkMonster = ( CTalkMonster * ) pFriend; m_hTalkTarget = pFriend; pTalkMonster->SetAnswerQuestion( this ); // UNDONE: This is EVIL!!! pTalkMonster->m_flStopTalkTime = m_flStopTalkTime; m_nSpeak++; return true; } } // otherwise, play an idle statement, try to face client when making a statement. if ( RANDOM_LONG(0,1) ) { //SENTENCEG_PlayRndSz( this, szIdleGroup, 1.0, ATTN_IDLE, 0, pitch ); CBaseEntity *pFriend = FindNearestFriend(true); if ( pFriend ) { m_hTalkTarget = pFriend; PlaySentence( szIdleGroup, duration, VOL_NORM, ATTN_IDLE ); m_nSpeak++; return true; } } // didn't speak Talk( 0 ); CTalkMonster::g_talkWaitTime = 0; return false; }
//========================================================= // sit, do stuff //========================================================= void CSittingScientist :: SittingThink( void ) { CBaseEntity *pent; StudioFrameAdvance( ); // try to greet player if (FIdleHello()) { pent = FindNearestFriend(TRUE); if (pent) { float yaw = VecToYaw(pent->pev->origin - pev->origin) - pev->angles.y; if (yaw > 180) yaw -= 360; if (yaw < -180) yaw += 360; if (yaw > 0) pev->sequence = m_baseSequence + SITTING_ANIM_sitlookleft; else pev->sequence = m_baseSequence + SITTING_ANIM_sitlookright; ResetSequenceInfo( ); pev->frame = 0; SetBoneController( 0, 0 ); } } else if (m_fSequenceFinished) { int i = RANDOM_LONG(0,99); m_headTurn = 0; if (m_flResponseDelay && gpGlobals->time > m_flResponseDelay) { // respond to question IdleRespond(); pev->sequence = m_baseSequence + SITTING_ANIM_sitscared; m_flResponseDelay = 0; } else if (i < 30) { pev->sequence = m_baseSequence + SITTING_ANIM_sitting3; // turn towards player or nearest friend and speak if (!FBitSet(m_bitsSaid, bit_saidHelloPlayer)) pent = FindNearestFriend(TRUE); else pent = FindNearestFriend(FALSE); if (!FIdleSpeak() || !pent) { m_headTurn = RANDOM_LONG(0,8) * 10 - 40; pev->sequence = m_baseSequence + SITTING_ANIM_sitting3; } else { // only turn head if we spoke float yaw = VecToYaw(pent->pev->origin - pev->origin) - pev->angles.y; if (yaw > 180) yaw -= 360; if (yaw < -180) yaw += 360; if (yaw > 0) pev->sequence = m_baseSequence + SITTING_ANIM_sitlookleft; else pev->sequence = m_baseSequence + SITTING_ANIM_sitlookright; //ALERT(at_console, "sitting speak\n"); } } else if (i < 60) { pev->sequence = m_baseSequence + SITTING_ANIM_sitting3; m_headTurn = RANDOM_LONG(0,8) * 10 - 40; if (RANDOM_LONG(0,99) < 5) { //ALERT(at_console, "sitting speak2\n"); FIdleSpeak(); } } else if (i < 80) { pev->sequence = m_baseSequence + SITTING_ANIM_sitting2; } else if (i < 100) { pev->sequence = m_baseSequence + SITTING_ANIM_sitscared; } ResetSequenceInfo( ); pev->frame = 0; SetBoneController( 0, m_headTurn ); } SetNextThink( 0.1 ); }
//========================================================= // 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; }
//========================================================= // 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; }