//========================================================= // 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; }
//========================================================= // 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; }
void CScientist::DeclineFollowing( void ) { Talk( 10 ); m_hTalkTarget = m_hEnemy; if ( FClassnameIs(pev, "monster_rosenberg")) PlaySentence( "RO_POK", 2, VOL_NORM, ATTN_NORM ); else PlaySentence( "SC_POK", 2, VOL_NORM, ATTN_NORM ); }
void CScientist :: Scream( void ) { if ( FOkToSpeak() ) { Talk( 10 ); m_hTalkTarget = m_hEnemy; if ( FClassnameIs(pev, "monster_rosenberg")) PlaySentence( "RO_SCREAM", RANDOM_FLOAT(3, 6), VOL_NORM, ATTN_NORM ); else PlaySentence( "SC_SCREAM", RANDOM_FLOAT(3, 6), VOL_NORM, ATTN_NORM ); } }
//========================================================= // IdleRespond // Respond to a previous question //========================================================= void CMTalkMonster :: IdleRespond( void ) { int pitch = GetVoicePitch(); // play response PlaySentence( m_szGrp[TLK_ANSWER], RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE ); }
//========================================================= // IdleRespond // Respond to a previous question //========================================================= void CTalkMonster :: IdleRespond( void ) { //GetVoicePitch mutates the random number generator so removing the call changes behavior - Solokiller /*int pitch = */GetVoicePitch(); // play response PlaySentence( m_szGrp[TLK_ANSWER], RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE ); }
int COtis :: TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType) { int ret; // make sure friends talk about it if player hurts talkmonsters... if ( !m_fHostile ) ret = CTalkMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType); else ret = CBaseMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType); if ( !IsAlive() || pev->deadflag == DEAD_DYING || m_fHostile ) return ret; if ( !m_fHostile ) { if ( m_MonsterState != MONSTERSTATE_PRONE && (pevAttacker->flags & FL_CLIENT) ) { m_flPlayerDamage += flDamage; // This is a heurstic to determine if the player intended to harm me // If I have an enemy, we can't establish intent (may just be crossfire) if ( m_hEnemy == NULL ) { // If the player was facing directly at me, or I'm already suspicious, get mad if ( (m_afMemory & bits_MEMORY_SUSPICIOUS) || IsFacing( pevAttacker, pev->origin ) ) { // Alright, now I'm pissed! PlaySentence( "OT_MAD", 4, VOL_NORM, ATTN_NORM ); Remember( bits_MEMORY_PROVOKED ); StopFollowing( TRUE ); } else { // Hey, be careful with that PlaySentence( "OT_SHOT", 4, VOL_NORM, ATTN_NORM ); Remember( bits_MEMORY_SUSPICIOUS ); } } else if ( !(m_hEnemy->IsPlayer()) && pev->deadflag == DEAD_NO ) PlaySentence( "OT_SHOT", 4, VOL_NORM, ATTN_NORM ); } } return ret; }
//========================================================= // ALertSound - otis says "Freeze!" //========================================================= void COtis :: AlertSound( void ) { if ( m_hEnemy != NULL ) { if ( FOkToSpeak() ) PlaySentence( "OT_ATTACK", RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE ); } }
void CScientist :: Scream( void ) { if ( FOkToSpeak() ) { Talk( 10 ); m_hTalkTarget = m_hEnemy; PlaySentence( "SC_SCREAM", RANDOM_FLOAT(3, 6), VOL_NORM, ATTN_NORM ); } }
//========================================================= // 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; }
//========================================================= // 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; }
void CMTalkMonster::StartFollowing( edict_t *pLeader ) { if ( m_hEnemy != NULL ) m_IdealMonsterState = MONSTERSTATE_ALERT; m_hTargetEnt = pLeader; PlaySentence( m_szGrp[TLK_USE], RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE ); m_hTalkTarget = m_hTargetEnt; ClearConditions( bits_COND_CLIENT_PUSH ); ClearSchedule(); }
void CTalkMonster::PlayScriptedSentence( const char *pszSentence, float duration, float volume, float attenuation, const bool bConcurrent, CBaseEntity *pListener ) { if ( !bConcurrent ) ShutUpFriends(); ClearConditions( bits_COND_CLIENT_PUSH ); // Forget about moving! I've got something to say! m_useTime = gpGlobals->time + duration; PlaySentence( pszSentence, duration, volume, attenuation ); m_hTalkTarget = pListener; }
//========================================================= // ALertSound - barney says "Freeze!" //========================================================= void CFriend :: AlertSound( void ) { if ( m_hEnemy != NULL ) { if ( FOkToSpeak() ) { if (m_iszSpeakAs) { char szBuf[32]; strcpy(szBuf,STRING(m_iszSpeakAs)); strcat(szBuf,"_ATTACK"); PlaySentence( szBuf, RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE ); } else { PlaySentence( "FG_ATTACK", RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE ); } } } }
void CHL1NPCTalker::StartFollowing( CBaseEntity *pLeader ) { if ( !HasSpawnFlags( SF_NPC_GAG ) ) { if ( m_iszUse != NULL_STRING ) { PlaySentence( STRING( m_iszUse ), 0.0f ); } else { Speak( TLK_STARTFOLLOW ); } SetSpeechTarget( pLeader ); } BaseClass::StartFollowing( pLeader ); }
void CTalkMonster :: HandleAnimEvent( AnimEvent_t& event ) { switch( event.event ) { case SCRIPT_EVENT_SENTENCE_RND1: // Play a named sentence group 25% of the time if (RANDOM_LONG(0,99) < 75) break; // fall through... case SCRIPT_EVENT_SENTENCE: // Play a named sentence group ShutUpFriends(); PlaySentence( event.options, RANDOM_FLOAT(2.8, 3.4), VOL_NORM, ATTN_IDLE ); //ALERT(at_console, "script event speak\n"); break; default: CBaseMonster::HandleAnimEvent( event ); break; } }
void CTalkMonster::StopFollowing( const bool clearSchedule ) { if ( IsFollowing() ) { if ( !(m_afMemory & bits_MEMORY_PROVOKED) ) { PlaySentence( m_szGrp[TLK_UNUSE], RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE ); m_hTalkTarget = m_hTargetEnt; } if ( m_movementGoal == MOVEGOAL_TARGETENT ) RouteClear(); // Stop him from walking toward the player m_hTargetEnt = NULL; if ( clearSchedule ) ClearSchedule(); if ( m_hEnemy != NULL ) m_IdealMonsterState = MONSTERSTATE_COMBAT; } }
// try to smell something void CTalkMonster :: TrySmellTalk( void ) { if ( !FOkToSpeak() ) return; // clear smell bits periodically if ( gpGlobals->time > m_flLastSaidSmelled ) { // ALERT ( at_aiconsole, "Clear smell bits\n" ); ClearBits(m_bitsSaid, bit_saidSmelled); } // smelled something? if (!FBitSet(m_bitsSaid, bit_saidSmelled) && HasConditions ( bits_COND_SMELL )) { PlaySentence( m_szGrp[TLK_SMELL], RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE ); m_flLastSaidSmelled = gpGlobals->time + 60;// don't talk about the stinky for a while. SetBits(m_bitsSaid, bit_saidSmelled); } }
//========================================================= // HandleAnimEvent - catches the NPC-specific messages // that occur when tagged animation frames are played. //========================================================= void CNPCSimpleTalker::HandleAnimEvent( animevent_t *pEvent ) { switch( pEvent->event ) { case SCRIPT_EVENT_SENTENCE_RND1: // Play a named sentence group 25% of the time if (random->RandomInt(0,99) < 75) break; // fall through... case SCRIPT_EVENT_SENTENCE: // Play a named sentence group ShutUpFriends(); PlaySentence( pEvent->options, random->RandomFloat(2.8, 3.4) ); //Msg( "script event speak\n"); break; default: BaseClass::HandleAnimEvent( pEvent ); break; } }
void CHL1NPCTalker::StopFollowing( void ) { if ( !(m_afMemory & bits_MEMORY_PROVOKED) ) { if ( !HasSpawnFlags( SF_NPC_GAG ) ) { if ( m_iszUnUse != NULL_STRING ) { PlaySentence( STRING( m_iszUnUse ), 0.0f ); } else { Speak( TLK_STOPFOLLOW ); } SetSpeechTarget( GetFollowTarget() ); } } BaseClass::StopFollowing(); }
void CScientist :: StartTask( Task_t *pTask ) { switch( pTask->iTask ) { case TASK_SAY_HEAL: // if ( FOkToSpeak() ) Talk( 2 ); m_hTalkTarget = m_hTargetEnt; PlaySentence( "SC_HEAL", 2, VOL_NORM, ATTN_IDLE ); TaskComplete(); break; case TASK_SCREAM: Scream(); TaskComplete(); break; case TASK_RANDOM_SCREAM: if ( RANDOM_FLOAT( 0, 1 ) < pTask->flData ) Scream(); TaskComplete(); break; case TASK_SAY_FEAR: if ( FOkToSpeak() ) { Talk( 2 ); m_hTalkTarget = m_hEnemy; if ( m_hEnemy->IsPlayer() ) PlaySentence( "SC_PLFEAR", 5, VOL_NORM, ATTN_NORM ); else PlaySentence( "SC_FEAR", 5, VOL_NORM, ATTN_NORM ); } TaskComplete(); break; case TASK_HEAL: m_IdealActivity = ACT_MELEE_ATTACK1; break; case TASK_RUN_PATH_SCARED: m_movementActivity = ACT_RUN_SCARED; break; case TASK_MOVE_TO_TARGET_RANGE_SCARED: { if ( (m_hTargetEnt->pev->origin - pev->origin).Length() < 1 ) TaskComplete(); else { m_vecMoveGoal = m_hTargetEnt->pev->origin; if ( !MoveToTarget( ACT_WALK_SCARED, 0.5 ) ) TaskFail(); } } break; default: CTalkMonster::StartTask( pTask ); break; } }
void CBarney::DeclineFollowing( void ) { PlaySentence( "BA_POK", 2, VOL_NORM, ATTN_NORM ); }
int CBarney :: TakeDamage( entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType) { // make sure friends talk about it if player hurts talkmonsters... int ret = CTalkMonster::TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType); if ( !IsAlive() || pev->deadflag == DEAD_DYING ) return ret; // LRC - if my reaction to the player has been overridden, don't do this stuff if (m_iPlayerReact) return ret; if ( m_MonsterState != MONSTERSTATE_PRONE && (pevAttacker->flags & FL_CLIENT) ) { m_flPlayerDamage += flDamage; // This is a heurstic to determine if the player intended to harm me // If I have an enemy, we can't establish intent (may just be crossfire) if ( m_hEnemy == NULL ) { // If the player was facing directly at me, or I'm already suspicious, get mad if( (m_afMemory & bits_MEMORY_SUSPICIOUS) || UTIL_IsFacing( pevAttacker, GetAbsOrigin() )) { // Alright, now I'm pissed! if (m_iszSpeakAs) { char szBuf[32]; strcpy(szBuf,STRING(m_iszSpeakAs)); strcat(szBuf,"_MAD"); PlaySentence( szBuf, 4, VOL_NORM, ATTN_NORM ); } else { PlaySentence( "BA_MAD", 4, VOL_NORM, ATTN_NORM ); } Remember( bits_MEMORY_PROVOKED ); StopFollowing( TRUE ); } else { // Hey, be careful with that if (m_iszSpeakAs) { char szBuf[32]; strcpy(szBuf,STRING(m_iszSpeakAs)); strcat(szBuf,"_SHOT"); PlaySentence( szBuf, 4, VOL_NORM, ATTN_NORM ); } else { PlaySentence( "BA_SHOT", 4, VOL_NORM, ATTN_NORM ); } Remember( bits_MEMORY_SUSPICIOUS ); } } else if ( !(m_hEnemy->IsPlayer()) && pev->deadflag == DEAD_NO ) { if (m_iszSpeakAs) { char szBuf[32]; strcpy(szBuf,STRING(m_iszSpeakAs)); strcat(szBuf,"_SHOT"); PlaySentence( szBuf, 4, VOL_NORM, ATTN_NORM ); } else { PlaySentence( "BA_SHOT", 4, VOL_NORM, ATTN_NORM ); } } } return ret; }
void CTalkMonster :: StartTask( const Task_t& task ) { switch ( task.iTask ) { case TASK_TLK_SPEAK: // ask question or make statement FIdleSpeak(); TaskComplete(); break; case TASK_TLK_RESPOND: // respond to question IdleRespond(); TaskComplete(); break; case TASK_TLK_HELLO: // greet player FIdleHello(); TaskComplete(); break; case TASK_TLK_STARE: // let the player know I know he's staring at me. FIdleStare(); TaskComplete(); break; case TASK_FACE_PLAYER: case TASK_TLK_LOOK_AT_CLIENT: case TASK_TLK_CLIENT_STARE: // track head to the client for a while. m_flWaitFinished = gpGlobals->time + task.flData; break; case TASK_TLK_EYECONTACT: break; case TASK_TLK_IDEALYAW: if (m_hTalkTarget != NULL) { SetYawSpeed( 60 ); float yaw = VecToYaw(m_hTalkTarget->GetAbsOrigin() - GetAbsOrigin()) - GetAbsAngles().y; if (yaw > 180) yaw -= 360; if (yaw < -180) yaw += 360; if (yaw < 0) { SetIdealYaw( min( yaw + 45, 0.0f ) + GetAbsAngles().y ); } else { SetIdealYaw( max( yaw - 45, 0.0f ) + GetAbsAngles().y ); } } TaskComplete(); break; case TASK_TLK_HEADRESET: // reset head position after looking at something m_hTalkTarget = NULL; TaskComplete(); break; case TASK_TLK_STOPSHOOTING: // tell player to stop shooting PlaySentence( m_szGrp[TLK_NOSHOOT], RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_NORM ); TaskComplete(); break; case TASK_CANT_FOLLOW: StopFollowing( false ); PlaySentence( m_szGrp[TLK_STOP], RANDOM_FLOAT(2, 2.5), VOL_NORM, ATTN_NORM ); TaskComplete(); break; case TASK_WALK_PATH_FOR_UNITS: m_movementActivity = ACT_WALK; break; case TASK_MOVE_AWAY_PATH: { Vector dir = GetAbsAngles(); dir.y = GetIdealYaw() + 180; Vector move; UTIL_MakeVectorsPrivate( dir, &move, nullptr, nullptr ); dir = GetAbsOrigin() + move * task.flData; if ( MoveToLocation( ACT_WALK, 2, dir ) ) { TaskComplete(); } else if ( FindCover( GetAbsOrigin(), GetViewOffset(), 0, CoverRadius() ) ) { // then try for plain ole cover m_flMoveWaitFinished = gpGlobals->time + 2; TaskComplete(); } else { // nowhere to go? TaskFail(); } } break; case TASK_PLAY_SCRIPT: m_hTalkTarget = NULL; CBaseMonster::StartTask( task ); break; default: CBaseMonster::StartTask( task ); } }
Schedule_t* CTalkMonster :: GetScheduleOfType ( int Type ) { switch( Type ) { case SCHED_MOVE_AWAY: return slMoveAway; case SCHED_MOVE_AWAY_FOLLOW: return slMoveAwayFollow; case SCHED_MOVE_AWAY_FAIL: return slMoveAwayFail; case SCHED_TARGET_FACE: // speak during 'use' if (RANDOM_LONG(0,99) < 2) //ALERT ( at_console, "target chase speak\n" ); return slIdleSpeakWait; else return slIdleStand; case SCHED_IDLE_STAND: { // if never seen player, try to greet him if (!FBitSet(m_bitsSaid, bit_saidHelloPlayer)) { return slIdleHello; } // sustained light wounds? if (!FBitSet(m_bitsSaid, bit_saidWoundLight) && ( GetHealth() <= ( GetMaxHealth() * 0.75))) { //SENTENCEG_PlayRndSz( this, m_szGrp[TLK_WOUND], 1.0, ATTN_IDLE, 0, GetVoicePitch() ); //CTalkMonster::g_talkWaitTime = gpGlobals->time + RANDOM_FLOAT(2.8, 3.2); PlaySentence( m_szGrp[TLK_WOUND], RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE ); SetBits(m_bitsSaid, bit_saidWoundLight); return slIdleStand; } // sustained heavy wounds? else if (!FBitSet(m_bitsSaid, bit_saidWoundHeavy) && ( GetHealth() <= ( GetMaxHealth() * 0.5))) { //SENTENCEG_PlayRndSz( this, m_szGrp[TLK_MORTAL], 1.0, ATTN_IDLE, 0, GetVoicePitch() ); //CTalkMonster::g_talkWaitTime = gpGlobals->time + RANDOM_FLOAT(2.8, 3.2); PlaySentence( m_szGrp[TLK_MORTAL], RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_IDLE ); SetBits(m_bitsSaid, bit_saidWoundHeavy); return slIdleStand; } // talk about world if (FOkToSpeak() && RANDOM_LONG(0,m_nSpeak * 2) == 0) { //ALERT ( at_console, "standing idle speak\n" ); return slIdleSpeak; } if ( !IsTalking() && HasConditions ( bits_COND_SEE_CLIENT ) && RANDOM_LONG( 0, 6 ) == 0 ) { edict_t *pPlayer = g_engfuncs.pfnPEntityOfEntIndex( 1 ); if ( pPlayer ) { // watch the client. UTIL_MakeVectors ( pPlayer->v.angles ); if ( ( pPlayer->v.origin - GetAbsOrigin() ).Length2D() < TLK_STARE_DIST && UTIL_DotPoints( pPlayer->v.origin, GetAbsOrigin(), gpGlobals->v_forward ) >= m_flFieldOfView ) { // go into the special STARE schedule if the player is close, and looking at me too. return &slTlkIdleWatchClient[ 1 ]; } return slTlkIdleWatchClient; } } else { if (IsTalking()) // look at who we're talking to return slTlkIdleEyecontact; else // regular standing idle return slIdleStand; } // NOTE - caller must first CTalkMonster::GetScheduleOfType, // then check result and decide what to return ie: if sci gets back // slIdleStand, return slIdleSciStand } break; } return CBaseMonster::GetScheduleOfType( Type ); }
//========================================================= // 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; }
//========================================================= // GetSchedule - 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. //========================================================= Schedule_t *CBarney :: GetSchedule ( void ) { if ( HasConditions( bits_COND_HEAR_SOUND ) ) { CSound *pSound; pSound = PBestSound(); ASSERT( pSound != NULL ); if ( pSound && (pSound->m_iType & bits_SOUND_DANGER) ) return GetScheduleOfType( SCHED_TAKE_COVER_FROM_BEST_SOUND ); } if ( HasConditions( bits_COND_ENEMY_DEAD ) && FOkToSpeak() ) { // Hey, be careful with that if (m_iszSpeakAs) { char szBuf[32]; strcpy(szBuf,STRING(m_iszSpeakAs)); strcat(szBuf,"_KILL"); PlaySentence( szBuf, 4, VOL_NORM, ATTN_NORM ); } else { PlaySentence( "BA_KILL", 4, VOL_NORM, ATTN_NORM ); } } switch( m_MonsterState ) { case MONSTERSTATE_COMBAT: { // dead enemy if ( HasConditions( bits_COND_ENEMY_DEAD ) ) { // call base class, all code to handle dead enemies is centralized there. return CBaseMonster :: GetSchedule(); } // always act surprized with a new enemy if ( HasConditions( bits_COND_NEW_ENEMY ) && HasConditions( bits_COND_LIGHT_DAMAGE) ) return GetScheduleOfType( SCHED_SMALL_FLINCH ); // wait for one schedule to draw gun if (!m_fGunDrawn ) return GetScheduleOfType( SCHED_ARM_WEAPON ); if ( HasConditions( bits_COND_HEAVY_DAMAGE ) ) return GetScheduleOfType( SCHED_TAKE_COVER_FROM_ENEMY ); } break; case MONSTERSTATE_ALERT: case MONSTERSTATE_IDLE: if ( HasConditions(bits_COND_LIGHT_DAMAGE | bits_COND_HEAVY_DAMAGE)) { // flinch if hurt return GetScheduleOfType( SCHED_SMALL_FLINCH ); } if ( m_hEnemy == NULL && IsFollowing() ) { if ( !m_hTargetEnt->IsAlive() ) { // UNDONE: Comment about the recently dead player here? StopFollowing( FALSE ); break; } else { if ( HasConditions( bits_COND_CLIENT_PUSH ) ) { return GetScheduleOfType( SCHED_MOVE_AWAY_FOLLOW ); } return GetScheduleOfType( SCHED_TARGET_FACE ); } } if ( HasConditions( bits_COND_CLIENT_PUSH ) ) { return GetScheduleOfType( SCHED_MOVE_AWAY ); } // try to say something about smells TrySmellTalk(); break; } return CTalkMonster::GetSchedule(); }
void CBarney::DeclineFollowing( void ) { PlaySentence( m_szGrp[TLK_DECLINE], 2, VOL_NORM, ATTN_NORM ); //LRC }
void CScientist::DeclineFollowing( void ) { Talk( 10 ); m_hTalkTarget = m_hEnemy; PlaySentence( m_szGrp[TLK_DECLINE], 2, VOL_NORM, ATTN_NORM ); //LRC }
void CMTalkMonster :: StartTask( Task_t *pTask ) { switch ( pTask->iTask ) { case TASK_TLK_SPEAK: // ask question or make statement FIdleSpeak(); TaskComplete(); break; case TASK_TLK_RESPOND: // respond to question IdleRespond(); TaskComplete(); break; case TASK_TLK_HELLO: // greet player FIdleHello(); TaskComplete(); break; case TASK_TLK_STARE: // let the player know I know he's staring at me. FIdleStare(); TaskComplete(); break; case TASK_FACE_PLAYER: case TASK_TLK_LOOK_AT_CLIENT: case TASK_TLK_CLIENT_STARE: // track head to the client for a while. m_flWaitFinished = gpGlobals->time + pTask->flData; break; case TASK_TLK_EYECONTACT: break; case TASK_TLK_IDEALYAW: if (m_hTalkTarget != NULL) { pev->yaw_speed = 60; float yaw = VecToYaw(m_hTalkTarget->v.origin - pev->origin) - pev->angles.y; if (yaw > 180) yaw -= 360; if (yaw < -180) yaw += 360; if (yaw < 0) { pev->ideal_yaw = min( yaw + 45.0f, 0.0f ) + pev->angles.y; } else { pev->ideal_yaw = max( yaw - 45.0f, 0.0f ) + pev->angles.y; } } TaskComplete(); break; case TASK_TLK_HEADRESET: // reset head position after looking at something m_hTalkTarget = NULL; TaskComplete(); break; case TASK_TLK_STOPSHOOTING: // tell player to stop shooting PlaySentence( m_szGrp[TLK_NOSHOOT], RANDOM_FLOAT(2.8, 3.2), VOL_NORM, ATTN_NORM ); TaskComplete(); break; case TASK_CANT_FOLLOW: StopFollowing( FALSE ); PlaySentence( m_szGrp[TLK_STOP], RANDOM_FLOAT(2, 2.5), VOL_NORM, ATTN_NORM ); TaskComplete(); break; case TASK_WALK_PATH_FOR_UNITS: m_movementActivity = ACT_WALK; break; case TASK_MOVE_AWAY_PATH: { Vector dir = pev->angles; dir.y = pev->ideal_yaw + 180; Vector move; UTIL_MakeVectorsPrivate( dir, move, NULL, NULL ); dir = pev->origin + move * pTask->flData; if ( MoveToLocation( ACT_WALK, 2, dir ) ) { TaskComplete(); } else if ( FindCover( pev->origin, pev->view_ofs, 0, CoverRadius() ) ) { // then try for plain ole cover m_flMoveWaitFinished = gpGlobals->time + 2; TaskComplete(); } else { // nowhere to go? TaskFail(); } } break; case TASK_PLAY_SCRIPT: m_hTalkTarget = NULL; CMBaseMonster::StartTask( pTask ); break; default: CMBaseMonster::StartTask( pTask ); } }