Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1353 lines
35 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "cbase.h"
  9. #include "npc_talker.h"
  10. #include "npcevent.h"
  11. #include "scriptevent.h"
  12. // memdbgon must be the last include file in a .cpp file!!!
  13. #include "tier0/memdbgon.h"
  14. BEGIN_SIMPLE_DATADESC( CNPCSimpleTalkerExpresser )
  15. // m_pSink (reconnected on load)
  16. DEFINE_AUTO_ARRAY( m_szMonologSentence, FIELD_CHARACTER ),
  17. DEFINE_FIELD( m_iMonologIndex, FIELD_INTEGER ),
  18. DEFINE_FIELD( m_fMonologSuspended, FIELD_BOOLEAN ),
  19. DEFINE_FIELD( m_hMonologTalkTarget, FIELD_EHANDLE ),
  20. END_DATADESC()
  21. BEGIN_DATADESC( CNPCSimpleTalker )
  22. DEFINE_FIELD( m_useTime, FIELD_TIME ),
  23. DEFINE_FIELD( m_flNextIdleSpeechTime, FIELD_TIME ),
  24. DEFINE_FIELD( m_nSpeak, FIELD_INTEGER ),
  25. DEFINE_FIELD( m_iszUse, FIELD_STRING ),
  26. DEFINE_FIELD( m_iszUnUse, FIELD_STRING ),
  27. // m_FollowBehavior (auto saved by AI)
  28. // Function Pointers
  29. DEFINE_USEFUNC( FollowerUse ),
  30. END_DATADESC()
  31. // array of friend names
  32. char *CNPCSimpleTalker::m_szFriends[TLK_CFRIENDS] =
  33. {
  34. "NPC_barney",
  35. "NPC_scientist",
  36. "NPC_sitting_scientist",
  37. NULL,
  38. };
  39. bool CNPCSimpleTalker::KeyValue( const char *szKeyName, const char *szValue )
  40. {
  41. if (FStrEq(szKeyName, "UseSentence"))
  42. {
  43. m_iszUse = AllocPooledString(szValue);
  44. }
  45. else if (FStrEq(szKeyName, "UnUseSentence"))
  46. {
  47. m_iszUnUse = AllocPooledString(szValue);
  48. }
  49. else
  50. return BaseClass::KeyValue( szKeyName, szValue );
  51. return true;
  52. }
  53. void CNPCSimpleTalker::Precache( void )
  54. {
  55. /*
  56. // FIXME: Need to figure out how to hook these...
  57. if ( m_iszUse != NULL_STRING )
  58. GetExpresser()->ModifyConcept( TLK_STARTFOLLOW, STRING( m_iszUse ) );
  59. if ( m_iszUnUse != NULL_STRING )
  60. GetExpresser()->ModifyConcept( TLK_STOPFOLLOW, STRING( m_iszUnUse ) );
  61. */
  62. BaseClass::Precache();
  63. }
  64. //-----------------------------------------------------------------------------
  65. // Purpose: Allows for modification of the interrupt mask for the current schedule.
  66. // In the most cases the base implementation should be called first.
  67. //-----------------------------------------------------------------------------
  68. void CNPCSimpleTalker::BuildScheduleTestBits( void )
  69. {
  70. BaseClass::BuildScheduleTestBits();
  71. // Assume that if I move from the player, I can respond to a question
  72. if ( ConditionInterruptsCurSchedule( COND_PLAYER_PUSHING ) || ConditionInterruptsCurSchedule( COND_PROVOKED ) )
  73. {
  74. SetCustomInterruptCondition( COND_TALKER_RESPOND_TO_QUESTION );
  75. }
  76. }
  77. void CNPCSimpleTalker::PrescheduleThink( void )
  78. {
  79. BaseClass::PrescheduleThink();
  80. (assert_cast<CNPCSimpleTalkerExpresser *>(GetExpresser()))->SpeakMonolog();
  81. }
  82. bool CNPCSimpleTalker::ShouldSuspendMonolog( void )
  83. {
  84. float flDist;
  85. flDist = ((assert_cast<CNPCSimpleTalkerExpresser *>(GetExpresser()))->GetMonologueTarget()->GetAbsOrigin() - GetAbsOrigin()).Length();
  86. if( flDist >= 384 )
  87. {
  88. return true;
  89. }
  90. return false;
  91. }
  92. bool CNPCSimpleTalker::ShouldResumeMonolog( void )
  93. {
  94. float flDist;
  95. if( HasCondition( COND_SEE_PLAYER ) )
  96. {
  97. flDist = ((assert_cast<CNPCSimpleTalkerExpresser *>(GetExpresser()))->GetMonologueTarget()->GetAbsOrigin() - GetAbsOrigin()).Length();
  98. if( flDist <= 256 )
  99. {
  100. return true;
  101. }
  102. }
  103. return false;
  104. }
  105. int CNPCSimpleTalker::SelectSchedule( void )
  106. {
  107. if ( !HasCondition(COND_RECEIVED_ORDERS) )
  108. {
  109. if ( GetState() == NPC_STATE_IDLE )
  110. {
  111. // if never seen player, try to greet him
  112. // Filter might be preventing us from ever greeting the player
  113. if ( HasCondition( COND_SEE_PLAYER ) && CanSayHello())
  114. {
  115. return SCHED_TALKER_IDLE_HELLO;
  116. }
  117. }
  118. }
  119. return BaseClass::SelectSchedule();
  120. }
  121. void CNPCSimpleTalker::StartTask( const Task_t *pTask )
  122. {
  123. switch ( pTask->iTask )
  124. {
  125. case TASK_TALKER_WAIT_FOR_SEMAPHORE:
  126. if ( GetExpresser()->SemaphoreIsAvailable( this ) )
  127. TaskComplete();
  128. break;
  129. case TASK_TALKER_SPEAK:
  130. // ask question or make statement
  131. FIdleSpeak();
  132. TaskComplete();
  133. break;
  134. case TASK_TALKER_RESPOND:
  135. // respond to question
  136. IdleRespond();
  137. TaskComplete();
  138. break;
  139. case TASK_TALKER_HELLO:
  140. // greet player
  141. FIdleHello();
  142. TaskComplete();
  143. break;
  144. case TASK_TALKER_STARE:
  145. // let the player know I know he's staring at me.
  146. FIdleStare();
  147. TaskComplete();
  148. break;
  149. case TASK_TALKER_LOOK_AT_CLIENT:
  150. case TASK_TALKER_CLIENT_STARE:
  151. // track head to the client for a while.
  152. SetWait( pTask->flTaskData );
  153. break;
  154. case TASK_TALKER_EYECONTACT:
  155. break;
  156. case TASK_TALKER_IDEALYAW:
  157. if (GetSpeechTarget() != NULL)
  158. {
  159. GetMotor()->SetIdealYawToTarget( GetSpeechTarget()->GetAbsOrigin() );
  160. }
  161. TaskComplete();
  162. break;
  163. case TASK_TALKER_HEADRESET:
  164. // reset head position after looking at something
  165. SetSpeechTarget( NULL );
  166. TaskComplete();
  167. break;
  168. case TASK_TALKER_BETRAYED:
  169. Speak( TLK_BETRAYED );
  170. TaskComplete();
  171. break;
  172. case TASK_TALKER_STOPSHOOTING:
  173. // tell player to stop shooting
  174. Speak( TLK_NOSHOOT );
  175. TaskComplete();
  176. break;
  177. default:
  178. BaseClass::StartTask( pTask );
  179. }
  180. }
  181. void CNPCSimpleTalker::RunTask( const Task_t *pTask )
  182. {
  183. switch( pTask->iTask )
  184. {
  185. case TASK_TALKER_WAIT_FOR_SEMAPHORE:
  186. if ( GetExpresser()->SemaphoreIsAvailable( this ) )
  187. TaskComplete();
  188. break;
  189. case TASK_TALKER_CLIENT_STARE:
  190. case TASK_TALKER_LOOK_AT_CLIENT:
  191. if ( pTask->iTask == TASK_TALKER_CLIENT_STARE && AI_IsSinglePlayer() )
  192. {
  193. // Get edict for one player
  194. CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
  195. Assert( pPlayer );
  196. // fail out if the player looks away or moves away.
  197. if ( ( pPlayer->GetAbsOrigin() - GetAbsOrigin() ).Length2D() > TALKER_STARE_DIST )
  198. {
  199. // player moved away.
  200. TaskFail("Player moved away");
  201. }
  202. Vector forward;
  203. AngleVectors( pPlayer->GetLocalAngles(), &forward );
  204. if ( UTIL_DotPoints( pPlayer->GetAbsOrigin(), GetAbsOrigin(), forward ) < m_flFieldOfView )
  205. {
  206. // player looked away
  207. TaskFail("Player looked away");
  208. }
  209. }
  210. if ( IsWaitFinished() )
  211. {
  212. TaskComplete();
  213. }
  214. break;
  215. case TASK_TALKER_EYECONTACT:
  216. if (IsMoving() || !GetExpresser()->IsSpeaking() || GetSpeechTarget() == NULL)
  217. {
  218. TaskComplete();
  219. }
  220. break;
  221. case TASK_WAIT_FOR_MOVEMENT:
  222. FIdleSpeakWhileMoving();
  223. BaseClass::RunTask( pTask );
  224. break;
  225. default:
  226. BaseClass::RunTask( pTask );
  227. }
  228. }
  229. //------------------------------------------------------------------------------
  230. // Purpose :
  231. // Input :
  232. // Output :
  233. //------------------------------------------------------------------------------
  234. Activity CNPCSimpleTalker::NPC_TranslateActivity( Activity eNewActivity )
  235. {
  236. if ((eNewActivity == ACT_IDLE) &&
  237. (GetExpresser()->IsSpeaking()) &&
  238. (SelectWeightedSequence ( ACT_SIGNAL3 ) != ACTIVITY_NOT_AVAILABLE) )
  239. {
  240. return ACT_SIGNAL3;
  241. }
  242. else if ((eNewActivity == ACT_SIGNAL3) &&
  243. (SelectWeightedSequence ( ACT_SIGNAL3 ) == ACTIVITY_NOT_AVAILABLE) )
  244. {
  245. return ACT_IDLE;
  246. }
  247. return BaseClass::NPC_TranslateActivity( eNewActivity );
  248. }
  249. void CNPCSimpleTalker::Event_Killed( const CTakeDamageInfo &info )
  250. {
  251. AlertFriends( info.GetAttacker() );
  252. if ( info.GetAttacker()->GetFlags() & FL_CLIENT )
  253. {
  254. LimitFollowers( info.GetAttacker(), 0 );
  255. }
  256. BaseClass::Event_Killed( info );
  257. }
  258. //-----------------------------------------------------------------------------
  259. // Purpose:
  260. //-----------------------------------------------------------------------------
  261. CBaseEntity *CNPCSimpleTalker::EnumFriends( CBaseEntity *pPrevious, int listNumber, bool bTrace )
  262. {
  263. CBaseEntity *pFriend = pPrevious;
  264. char *pszFriend;
  265. trace_t tr;
  266. Vector vecCheck;
  267. pszFriend = m_szFriends[ FriendNumber(listNumber) ];
  268. while ( pszFriend != NULL && ((pFriend = gEntList.FindEntityByClassname( pFriend, pszFriend )) != NULL) )
  269. {
  270. if (pFriend == this || !pFriend->IsAlive())
  271. // don't talk to self or dead people
  272. continue;
  273. if ( bTrace )
  274. {
  275. Vector vecCheck;
  276. pFriend->CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.5f, 1.0f ), &vecCheck );
  277. UTIL_TraceLine( GetAbsOrigin(), vecCheck, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr);
  278. }
  279. else
  280. {
  281. tr.fraction = 1.0;
  282. }
  283. if (tr.fraction == 1.0)
  284. {
  285. return pFriend;
  286. }
  287. }
  288. return NULL;
  289. }
  290. //-----------------------------------------------------------------------------
  291. // Purpose:
  292. // Input : *pKiller -
  293. //-----------------------------------------------------------------------------
  294. void CNPCSimpleTalker::AlertFriends( CBaseEntity *pKiller )
  295. {
  296. CBaseEntity *pFriend = NULL;
  297. int i;
  298. // for each friend in this bsp...
  299. for ( i = 0; i < TLK_CFRIENDS; i++ )
  300. {
  301. while ((pFriend = EnumFriends( pFriend, i, true )) != NULL )
  302. {
  303. CAI_BaseNPC *pNPC = pFriend->MyNPCPointer();
  304. if ( pNPC->IsAlive() )
  305. {
  306. // If a client killed me, make everyone else mad/afraid of him
  307. if ( pKiller->GetFlags() & FL_CLIENT )
  308. {
  309. CNPCSimpleTalker*pTalkNPC = (CNPCSimpleTalker *)pFriend;
  310. if (pTalkNPC && pTalkNPC->IsOkToCombatSpeak())
  311. {
  312. // FIXME: need to check CanSpeakConcept?
  313. pTalkNPC->Speak( TLK_BETRAYED );
  314. }
  315. }
  316. else
  317. {
  318. if( IRelationType(pKiller) == D_HT)
  319. {
  320. // Killed by an enemy!!!
  321. CNPCSimpleTalker *pAlly = (CNPCSimpleTalker *)pNPC;
  322. if( pAlly && pAlly->GetExpresser()->CanSpeakConcept( TLK_ALLY_KILLED ) )
  323. {
  324. pAlly->Speak( TLK_ALLY_KILLED );
  325. }
  326. }
  327. }
  328. }
  329. }
  330. }
  331. }
  332. //-----------------------------------------------------------------------------
  333. // Purpose:
  334. //-----------------------------------------------------------------------------
  335. void CNPCSimpleTalker::ShutUpFriends( void )
  336. {
  337. CBaseEntity *pFriend = NULL;
  338. int i;
  339. // for each friend in this bsp...
  340. for ( i = 0; i < TLK_CFRIENDS; i++ )
  341. {
  342. while ((pFriend = EnumFriends( pFriend, i, true )) != NULL)
  343. {
  344. CAI_BaseNPC *pNPC = pFriend->MyNPCPointer();
  345. if ( pNPC )
  346. {
  347. pNPC->SentenceStop();
  348. }
  349. }
  350. }
  351. }
  352. // UNDONE: Keep a follow time in each follower, make a list of followers in this function and do LRU
  353. // UNDONE: Check this in Restore to keep restored NPCs from joining a full list of followers
  354. void CNPCSimpleTalker::LimitFollowers( CBaseEntity *pPlayer, int maxFollowers )
  355. {
  356. CBaseEntity *pFriend = NULL;
  357. int i, count;
  358. count = 0;
  359. // for each friend in this bsp...
  360. for ( i = 0; i < TLK_CFRIENDS; i++ )
  361. {
  362. while ((pFriend = EnumFriends( pFriend, i, false )) != NULL)
  363. {
  364. CAI_BaseNPC *pNPC = pFriend->MyNPCPointer();
  365. CNPCSimpleTalker *pTalker;
  366. if ( pNPC )
  367. {
  368. if ( pNPC->GetTarget() == pPlayer )
  369. {
  370. count++;
  371. if ( count > maxFollowers && (pTalker = dynamic_cast<CNPCSimpleTalker *>( pNPC ) ) != NULL )
  372. pTalker->StopFollowing();
  373. }
  374. }
  375. }
  376. }
  377. }
  378. //=========================================================
  379. // HandleAnimEvent - catches the NPC-specific messages
  380. // that occur when tagged animation frames are played.
  381. //=========================================================
  382. void CNPCSimpleTalker::HandleAnimEvent( animevent_t *pEvent )
  383. {
  384. switch( pEvent->event )
  385. {
  386. case SCRIPT_EVENT_SENTENCE_RND1: // Play a named sentence group 25% of the time
  387. if (random->RandomInt(0,99) < 75)
  388. break;
  389. // fall through...
  390. case SCRIPT_EVENT_SENTENCE: // Play a named sentence group
  391. ShutUpFriends();
  392. PlaySentence( pEvent->options, random->RandomFloat(2.8, 3.4) );
  393. //Msg( "script event speak\n");
  394. break;
  395. default:
  396. BaseClass::HandleAnimEvent( pEvent );
  397. break;
  398. }
  399. }
  400. //-----------------------------------------------------------------------------
  401. // Purpose: Scan for nearest, visible friend. If fPlayer is true, look for nearest player
  402. //-----------------------------------------------------------------------------
  403. bool CNPCSimpleTalker::IsValidSpeechTarget( int flags, CBaseEntity *pEntity )
  404. {
  405. return BaseClass::IsValidSpeechTarget( flags, pEntity );
  406. }
  407. CBaseEntity *CNPCSimpleTalker::FindNearestFriend(bool fPlayer)
  408. {
  409. return FindSpeechTarget( (fPlayer) ? AIST_PLAYERS : AIST_NPCS );
  410. }
  411. //-----------------------------------------------------------------------------
  412. //-----------------------------------------------------------------------------
  413. // Purpose: Respond to a previous question
  414. //-----------------------------------------------------------------------------
  415. void CNPCSimpleTalker::IdleRespond( void )
  416. {
  417. if (!IsOkToSpeak())
  418. return;
  419. // play response
  420. SpeakAnswerFriend( GetSpeechTarget() );
  421. DeferAllIdleSpeech( random->RandomFloat( TALKER_DEFER_IDLE_SPEAK_MIN, TALKER_DEFER_IDLE_SPEAK_MAX ) );
  422. }
  423. bool CNPCSimpleTalker::IsOkToSpeak( void )
  424. {
  425. if ( m_flNextIdleSpeechTime > gpGlobals->curtime )
  426. return false;
  427. return BaseClass::IsOkToSpeak();
  428. }
  429. //-----------------------------------------------------------------------------
  430. // Purpose: Find a nearby friend to stare at
  431. //-----------------------------------------------------------------------------
  432. int CNPCSimpleTalker::FIdleStare( void )
  433. {
  434. // Don't idly speak if our speech filter is preventing us
  435. if ( GetSpeechFilter() && GetSpeechFilter()->GetIdleModifier() == 0 )
  436. return true;
  437. SpeakIfAllowed( TLK_STARE );
  438. SetSpeechTarget( FindNearestFriend( true ) );
  439. return true;
  440. }
  441. //-----------------------------------------------------------------------------
  442. // Purpose: Try to greet player first time he's seen
  443. // Output : int
  444. //-----------------------------------------------------------------------------
  445. int CNPCSimpleTalker::FIdleHello( void )
  446. {
  447. // Filter might be preventing us from ever greeting the player
  448. if ( !CanSayHello() )
  449. return false;
  450. // get a player
  451. CBaseEntity *pPlayer = FindNearestFriend(true);
  452. if (pPlayer)
  453. {
  454. if (FInViewCone(pPlayer) && FVisible(pPlayer))
  455. {
  456. SayHelloToPlayer( pPlayer );
  457. return true;
  458. }
  459. }
  460. return false;
  461. }
  462. //-----------------------------------------------------------------------------
  463. // Purpose: Say hello to the specified player
  464. //-----------------------------------------------------------------------------
  465. void CNPCSimpleTalker::SayHelloToPlayer( CBaseEntity *pPlayer )
  466. {
  467. Assert( !GetExpresser()->SpokeConcept(TLK_HELLO) );
  468. SetSpeechTarget( pPlayer );
  469. Speak( TLK_HELLO );
  470. DeferAllIdleSpeech( random->RandomFloat( 5, 10 ) );
  471. CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs();
  472. CAI_PlayerAlly *pTalker;
  473. for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ )
  474. {
  475. pTalker = dynamic_cast<CAI_PlayerAlly *>(ppAIs[i]);
  476. if( pTalker && FVisible( pTalker ) )
  477. {
  478. // Tell this guy he's already said hello to the player, too.
  479. pTalker->GetExpresser()->SetSpokeConcept( TLK_HELLO, NULL );
  480. }
  481. }
  482. }
  483. //---------------------------------------------------------
  484. // Stop all allies from idle speech for a fixed amount
  485. // of time. Mostly filthy hack to hold us over until
  486. // acting comes online.
  487. //---------------------------------------------------------
  488. void CNPCSimpleTalker::DeferAllIdleSpeech( float flDelay, CAI_BaseNPC *pIgnore )
  489. {
  490. // Brute force. Just plow through NPC list looking for talkers.
  491. CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs();
  492. CNPCSimpleTalker *pTalker;
  493. float flTime = gpGlobals->curtime + flDelay;
  494. for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ )
  495. {
  496. if( ppAIs[i] != pIgnore )
  497. {
  498. pTalker = dynamic_cast<CNPCSimpleTalker *>(ppAIs[i]);
  499. if( pTalker )
  500. {
  501. pTalker->m_flNextIdleSpeechTime = flTime;
  502. }
  503. }
  504. }
  505. BaseClass::DeferAllIdleSpeech( flDelay, pIgnore );
  506. }
  507. //=========================================================
  508. // FIdleSpeak
  509. // ask question of nearby friend, or make statement
  510. //=========================================================
  511. int CNPCSimpleTalker::FIdleSpeak( void )
  512. {
  513. // try to start a conversation, or make statement
  514. int pitch;
  515. if (!IsOkToSpeak())
  516. return false;
  517. Assert( GetExpresser()->SemaphoreIsAvailable( this ) );
  518. pitch = GetExpresser()->GetVoicePitch();
  519. // player using this entity is alive and wounded?
  520. CBaseEntity *pTarget = GetTarget();
  521. if ( pTarget != NULL )
  522. {
  523. if ( pTarget->IsPlayer() )
  524. {
  525. if ( pTarget->IsAlive() )
  526. {
  527. SetSpeechTarget( GetTarget() );
  528. if (GetExpresser()->CanSpeakConcept( TLK_PLHURT3) &&
  529. (GetTarget()->m_iHealth <= GetTarget()->m_iMaxHealth / 8))
  530. {
  531. Speak( TLK_PLHURT3 );
  532. return true;
  533. }
  534. else if (GetExpresser()->CanSpeakConcept( TLK_PLHURT2) &&
  535. (GetTarget()->m_iHealth <= GetTarget()->m_iMaxHealth / 4))
  536. {
  537. Speak( TLK_PLHURT2 );
  538. return true;
  539. }
  540. else if (GetExpresser()->CanSpeakConcept( TLK_PLHURT1) &&
  541. (GetTarget()->m_iHealth <= GetTarget()->m_iMaxHealth / 2))
  542. {
  543. Speak( TLK_PLHURT1 );
  544. return true;
  545. }
  546. }
  547. else
  548. {
  549. //!!!KELLY - here's a cool spot to have the talkNPC talk about the dead player if we want.
  550. // "Oh dear, Gordon Freeman is dead!" -Scientist
  551. // "Damn, I can't do this without you." -Barney
  552. }
  553. }
  554. }
  555. // ROBIN: Disabled idle question & answer for now
  556. /*
  557. // if there is a friend nearby to speak to, play sentence, set friend's response time, return
  558. CBaseEntity *pFriend = FindNearestFriend(false);
  559. // 75% chance of talking to another citizen if one is available.
  560. if (pFriend && !(pFriend->IsMoving()) && random->RandomInt( 0, 3 ) != 0 )
  561. {
  562. if ( SpeakQuestionFriend( pFriend ) )
  563. {
  564. // force friend to answer
  565. CAI_PlayerAlly *pTalkNPC = dynamic_cast<CAI_PlayerAlly *>(pFriend);
  566. if (pTalkNPC && !pTalkNPC->HasSpawnFlags(SF_NPC_GAG) && !pTalkNPC->IsInAScript() )
  567. {
  568. SetSpeechTarget( pFriend );
  569. pTalkNPC->SetAnswerQuestion( this );
  570. pTalkNPC->GetExpresser()->BlockSpeechUntil( GetExpresser()->GetTimeSpeechComplete() );
  571. m_nSpeak++;
  572. }
  573. // Don't let anyone else butt in.
  574. DeferAllIdleSpeech( random->RandomFloat( TALKER_DEFER_IDLE_SPEAK_MIN, TALKER_DEFER_IDLE_SPEAK_MAX ), pTalkNPC );
  575. return true;
  576. }
  577. }
  578. */
  579. // Otherwise, play an idle statement, try to face client when making a statement.
  580. CBaseEntity *pFriend = FindNearestFriend(true);
  581. if ( pFriend )
  582. {
  583. SetSpeechTarget( pFriend );
  584. // If we're about to talk to the player, and we've never said hello, say hello first
  585. if ( !GetSpeechFilter() || !GetSpeechFilter()->NeverSayHello() )
  586. {
  587. if ( GetExpresser()->CanSpeakConcept( TLK_HELLO ) && !GetExpresser()->SpokeConcept( TLK_HELLO ) )
  588. {
  589. SayHelloToPlayer( pFriend );
  590. return true;
  591. }
  592. }
  593. if ( Speak( TLK_IDLE ) )
  594. {
  595. DeferAllIdleSpeech( random->RandomFloat( TALKER_DEFER_IDLE_SPEAK_MIN, TALKER_DEFER_IDLE_SPEAK_MAX ) );
  596. m_nSpeak++;
  597. }
  598. else
  599. {
  600. // We failed to speak. Don't try again for a bit.
  601. m_flNextIdleSpeechTime = gpGlobals->curtime + 3;
  602. }
  603. return true;
  604. }
  605. // didn't speak
  606. m_flNextIdleSpeechTime = gpGlobals->curtime + 3;
  607. return false;
  608. }
  609. //-----------------------------------------------------------------------------
  610. // Purpose: Speak the right question based upon who we're asking
  611. //-----------------------------------------------------------------------------
  612. bool CNPCSimpleTalker::SpeakQuestionFriend( CBaseEntity *pFriend )
  613. {
  614. return Speak( TLK_QUESTION );
  615. }
  616. //-----------------------------------------------------------------------------
  617. // Purpose: Speak the right answer based upon who we're answering
  618. //-----------------------------------------------------------------------------
  619. bool CNPCSimpleTalker::SpeakAnswerFriend( CBaseEntity *pFriend )
  620. {
  621. return Speak( TLK_ANSWER );
  622. }
  623. //-----------------------------------------------------------------------------
  624. // Purpose:
  625. //-----------------------------------------------------------------------------
  626. void CNPCSimpleTalker::FIdleSpeakWhileMoving( void )
  627. {
  628. if ( GetExpresser()->CanSpeak() )
  629. {
  630. if (!GetExpresser()->IsSpeaking() || GetSpeechTarget() == NULL)
  631. {
  632. // override so that during walk, a scientist may talk and greet player
  633. FIdleHello();
  634. if ( ShouldSpeakRandom( m_nSpeak * 20, GetSpeechFilter() ? GetSpeechFilter()->GetIdleModifier() : 1.0 ) )
  635. {
  636. FIdleSpeak();
  637. }
  638. }
  639. }
  640. }
  641. //-----------------------------------------------------------------------------
  642. // Purpose:
  643. //-----------------------------------------------------------------------------
  644. int CNPCSimpleTalker::PlayScriptedSentence( const char *pszSentence, float delay, float volume, soundlevel_t soundlevel, bool bConcurrent, CBaseEntity *pListener )
  645. {
  646. if ( !bConcurrent )
  647. ShutUpFriends();
  648. int sentenceIndex = BaseClass::PlayScriptedSentence( pszSentence, delay, volume, soundlevel, bConcurrent, pListener );
  649. delay += engine->SentenceLength( sentenceIndex );
  650. if ( delay < 0 )
  651. delay = 0;
  652. m_useTime = gpGlobals->curtime + delay;
  653. // Stop all idle speech until after the sentence has completed
  654. DeferAllIdleSpeech( delay + random->RandomInt( 3.0f, 5.0f ) );
  655. return sentenceIndex;
  656. }
  657. //-----------------------------------------------------------------------------
  658. // Purpose: Tell this NPC to answer a question from another NPC
  659. //-----------------------------------------------------------------------------
  660. void CNPCSimpleTalker::SetAnswerQuestion( CNPCSimpleTalker *pSpeaker )
  661. {
  662. if ( !m_hCine )
  663. {
  664. SetCondition( COND_TALKER_RESPOND_TO_QUESTION );
  665. }
  666. SetSpeechTarget( (CAI_BaseNPC *)pSpeaker );
  667. }
  668. //-----------------------------------------------------------------------------
  669. // Purpose:
  670. //-----------------------------------------------------------------------------
  671. int CNPCSimpleTalker::OnTakeDamage_Alive( const CTakeDamageInfo &info )
  672. {
  673. CTakeDamageInfo subInfo = info;
  674. // if player damaged this entity, have other friends talk about it.
  675. if (subInfo.GetAttacker() && (subInfo.GetAttacker()->GetFlags() & FL_CLIENT) && subInfo.GetDamage() < GetHealth() )
  676. {
  677. CBaseEntity *pFriend = FindNearestFriend(false);
  678. if (pFriend && pFriend->IsAlive())
  679. {
  680. // only if not dead or dying!
  681. CNPCSimpleTalker *pTalkNPC = (CNPCSimpleTalker *)pFriend;
  682. if (pTalkNPC && pTalkNPC->IsOkToCombatSpeak())
  683. {
  684. pTalkNPC->Speak( TLK_NOSHOOT );
  685. }
  686. }
  687. }
  688. return BaseClass::OnTakeDamage_Alive( subInfo );
  689. }
  690. int CNPCSimpleTalker::SelectNonCombatSpeechSchedule()
  691. {
  692. if ( !IsOkToSpeak() )
  693. return SCHED_NONE;
  694. // talk about world
  695. if ( ShouldSpeakRandom( m_nSpeak * 2, GetSpeechFilter() ? GetSpeechFilter()->GetIdleModifier() : 1.0 ) )
  696. {
  697. //Msg("standing idle speak\n" );
  698. return SCHED_TALKER_IDLE_SPEAK;
  699. }
  700. // failed to speak, so look at the player if he's around
  701. if ( AI_IsSinglePlayer() && GetExpresser()->CanSpeak() && HasCondition ( COND_SEE_PLAYER ) && random->RandomInt( 0, 6 ) == 0 )
  702. {
  703. CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
  704. Assert( pPlayer );
  705. if ( pPlayer )
  706. {
  707. // watch the client.
  708. Vector forward;
  709. AngleVectors( pPlayer->GetLocalAngles(), &forward );
  710. if ( ( pPlayer->GetAbsOrigin() - GetAbsOrigin() ).Length2D() < TALKER_STARE_DIST &&
  711. UTIL_DotPoints( pPlayer->GetAbsOrigin(), GetAbsOrigin(), forward ) >= m_flFieldOfView )
  712. {
  713. // go into the special STARE schedule if the player is close, and looking at me too.
  714. return SCHED_TALKER_IDLE_WATCH_CLIENT_STARE;
  715. }
  716. return SCHED_TALKER_IDLE_WATCH_CLIENT;
  717. }
  718. }
  719. else
  720. {
  721. // look at who we're talking to
  722. if ( GetSpeechTarget() && GetExpresser()->IsSpeaking() )
  723. return SCHED_TALKER_IDLE_EYE_CONTACT;
  724. }
  725. return SCHED_NONE;
  726. }
  727. //-----------------------------------------------------------------------------
  728. // Purpose:
  729. // Output : Returns true on success, false on failure.
  730. //-----------------------------------------------------------------------------
  731. bool CNPCSimpleTalker::CanSayHello( void )
  732. {
  733. #ifndef HL1_DLL
  734. if ( Classify() == CLASS_PLAYER_ALLY_VITAL )
  735. return false;
  736. #endif
  737. if ( GetSpeechFilter() && GetSpeechFilter()->NeverSayHello() )
  738. return false;
  739. if ( !GetExpresser()->CanSpeakConcept(TLK_HELLO) || GetExpresser()->SpokeConcept(TLK_HELLO) )
  740. return false;
  741. if ( !IsOkToSpeak() )
  742. return false;
  743. return true;
  744. }
  745. void CNPCSimpleTalker::OnStartingFollow( CBaseEntity *pTarget )
  746. {
  747. GetExpresser()->SetSpokeConcept( TLK_HELLO, NULL ); // Don't say hi after you've started following
  748. if ( IsOkToSpeak() ) // don't speak if idle talk is blocked. player commanded/use follow will always speak
  749. Speak( TLK_STARTFOLLOW );
  750. SetSpeechTarget( GetTarget() );
  751. ClearCondition( COND_PLAYER_PUSHING );
  752. }
  753. void CNPCSimpleTalker::OnStoppingFollow( CBaseEntity *pTarget )
  754. {
  755. if ( !(m_afMemory & bits_MEMORY_PROVOKED) )
  756. {
  757. if ( IsOkToCombatSpeak() )
  758. {
  759. if ( pTarget == NULL )
  760. Speak( TLK_STOPFOLLOW );
  761. else
  762. Speak( TLK_STOP );
  763. }
  764. SetSpeechTarget( FindNearestFriend(true) );
  765. }
  766. }
  767. void CNPCSimpleTalker::FollowerUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
  768. {
  769. // Don't allow use during a scripted_sentence
  770. if ( m_useTime > gpGlobals->curtime )
  771. return;
  772. if ( pCaller != NULL && pCaller->IsPlayer() )
  773. {
  774. if ( !m_FollowBehavior.GetFollowTarget() && IsInterruptable() )
  775. {
  776. #if TOML_TODO
  777. LimitFollowers( pCaller , 1 );
  778. #endif
  779. if ( m_afMemory & bits_MEMORY_PROVOKED )
  780. Msg( "I'm not following you, you evil person!\n" );
  781. else
  782. {
  783. StartFollowing( pCaller );
  784. }
  785. }
  786. else
  787. {
  788. StopFollowing();
  789. }
  790. }
  791. }
  792. //-----------------------------------------------------------------------------
  793. void CNPCSimpleTalker::InputIdleRespond( inputdata_t &inputdata )
  794. {
  795. // We've been told to respond. Check combat speak, not isoktospeak, because
  796. // we don't want to check the idle speech time.
  797. if (!IsOkToCombatSpeak())
  798. return;
  799. IdleRespond();
  800. }
  801. int CNPCSimpleTalkerExpresser::SpeakRawSentence( const char *pszSentence, float delay, float volume, soundlevel_t soundlevel, CBaseEntity *pListener )
  802. {
  803. char szSpecificSentence[1024];
  804. int sentenceIndex = -1;
  805. if ( !pszSentence )
  806. return sentenceIndex;
  807. if ( pszSentence[0] == AI_SP_START_MONOLOG )
  808. {
  809. // this sentence command will start this NPC speaking
  810. // lengthy monolog from smaller sentences.
  811. BeginMonolog( (char *)pszSentence, pListener );
  812. return -1;
  813. }
  814. else if ( pszSentence[0] == AI_SP_MONOLOG_LINE )
  815. {
  816. Q_strncpy(szSpecificSentence, pszSentence, sizeof(szSpecificSentence) );
  817. szSpecificSentence[0] = AI_SP_SPECIFIC_SENTENCE;
  818. pszSentence = szSpecificSentence;
  819. }
  820. else
  821. {
  822. // this bit of speech is interrupting my monolog!
  823. SuspendMonolog( 0 );
  824. }
  825. return CAI_Expresser::SpeakRawSentence( pszSentence, delay, volume, soundlevel, pListener );
  826. }
  827. //-------------------------------------
  828. void CNPCSimpleTalkerExpresser::BeginMonolog( char *pszSentenceName, CBaseEntity *pListener )
  829. {
  830. if( pListener )
  831. {
  832. m_hMonologTalkTarget = pListener;
  833. }
  834. else
  835. {
  836. Warning( "NULL Listener in BeginMonolog()!\n" );
  837. Assert(0);
  838. EndMonolog();
  839. return;
  840. }
  841. Q_strncpy( m_szMonologSentence, pszSentenceName ,sizeof(m_szMonologSentence));
  842. // change the "AI_SP_START_MONOLOG" to an "AI_SP_MONOLOG_LINE". m_sMonologSentence is now the
  843. // string we'll tack numbers onto to play sentences from this group in
  844. // sequential order.
  845. m_szMonologSentence[0] = AI_SP_MONOLOG_LINE;
  846. m_fMonologSuspended = false;
  847. m_iMonologIndex = 0;
  848. }
  849. //-------------------------------------
  850. void CNPCSimpleTalkerExpresser::EndMonolog( void )
  851. {
  852. m_szMonologSentence[0] = 0;
  853. m_iMonologIndex = -1;
  854. m_fMonologSuspended = false;
  855. m_hMonologTalkTarget = NULL;
  856. }
  857. //-------------------------------------
  858. void CNPCSimpleTalkerExpresser::SpeakMonolog( void )
  859. {
  860. int i;
  861. char szSentence[ MONOLOGNAME_LEN ];
  862. if( !HasMonolog() )
  863. {
  864. return;
  865. }
  866. if( CanSpeak() )
  867. {
  868. if( m_fMonologSuspended )
  869. {
  870. if ( GetOuter()->ShouldResumeMonolog() )
  871. {
  872. ResumeMonolog();
  873. }
  874. return;
  875. }
  876. Q_snprintf( szSentence,sizeof(szSentence), "%s%d", m_szMonologSentence, m_iMonologIndex );
  877. m_iMonologIndex++;
  878. i = SpeakRawSentence( szSentence, 0, VOL_NORM );
  879. if ( i == -1 )
  880. {
  881. EndMonolog();
  882. }
  883. }
  884. else
  885. {
  886. if( GetOuter()->ShouldSuspendMonolog() )
  887. {
  888. SuspendMonolog( 0 );
  889. }
  890. }
  891. }
  892. //-------------------------------------
  893. void CNPCSimpleTalkerExpresser::SuspendMonolog( float flInterval )
  894. {
  895. if( HasMonolog() )
  896. {
  897. m_fMonologSuspended = true;
  898. }
  899. // free up other characters to speak.
  900. if ( GetSink()->UseSemaphore() )
  901. {
  902. GetSpeechSemaphore( GetOuter() )->Release();
  903. }
  904. }
  905. //-------------------------------------
  906. void CNPCSimpleTalkerExpresser::ResumeMonolog( void )
  907. {
  908. if( m_iMonologIndex > 0 )
  909. {
  910. // back up and repeat what I was saying
  911. // when interrupted.
  912. m_iMonologIndex--;
  913. }
  914. GetOuter()->OnResumeMonolog();
  915. m_fMonologSuspended = false;
  916. }
  917. // try to smell something
  918. void CNPCSimpleTalker::TrySmellTalk( void )
  919. {
  920. if ( !IsOkToSpeak() )
  921. return;
  922. if ( HasCondition( COND_SMELL ) && GetExpresser()->CanSpeakConcept( TLK_SMELL ) )
  923. Speak( TLK_SMELL );
  924. }
  925. void CNPCSimpleTalker::OnChangeRunningBehavior( CAI_BehaviorBase *pOldBehavior, CAI_BehaviorBase *pNewBehavior )
  926. {
  927. BaseClass::OnChangeRunningBehavior( pOldBehavior, pNewBehavior );
  928. CAI_FollowBehavior *pFollowBehavior;
  929. if ( ( pFollowBehavior = dynamic_cast<CAI_FollowBehavior *>(pNewBehavior) ) != NULL )
  930. {
  931. OnStartingFollow( pFollowBehavior->GetFollowTarget() );
  932. }
  933. else if ( ( pFollowBehavior = dynamic_cast<CAI_FollowBehavior *>(pOldBehavior) ) != NULL )
  934. {
  935. OnStoppingFollow( pFollowBehavior->GetFollowTarget() );
  936. }
  937. }
  938. bool CNPCSimpleTalker::OnBehaviorChangeStatus( CAI_BehaviorBase *pBehavior, bool fCanFinishSchedule )
  939. {
  940. bool interrupt = BaseClass::OnBehaviorChangeStatus( pBehavior, fCanFinishSchedule );
  941. if ( !interrupt )
  942. {
  943. interrupt = ( dynamic_cast<CAI_FollowBehavior *>(pBehavior) != NULL && ( m_NPCState == NPC_STATE_IDLE || m_NPCState == NPC_STATE_ALERT ) );
  944. }
  945. return interrupt;
  946. }
  947. //-----------------------------------------------------------------------------
  948. // Purpose: Return true if I should speak based on the chance & the speech filter's modifier
  949. //-----------------------------------------------------------------------------
  950. bool CNPCSimpleTalker::ShouldSpeakRandom( int iChance, float flModifier )
  951. {
  952. if ( flModifier != 1.0 )
  953. {
  954. // Avoid divide by zero
  955. if ( !flModifier )
  956. return false;
  957. iChance = floor( (float)iChance / flModifier );
  958. }
  959. return (random->RandomInt(0,iChance) == 0);
  960. }
  961. AI_BEGIN_CUSTOM_NPC(talk_monster,CNPCSimpleTalker)
  962. DECLARE_USES_SCHEDULE_PROVIDER( CAI_FollowBehavior )
  963. DECLARE_TASK(TASK_TALKER_RESPOND)
  964. DECLARE_TASK(TASK_TALKER_SPEAK)
  965. DECLARE_TASK(TASK_TALKER_HELLO)
  966. DECLARE_TASK(TASK_TALKER_BETRAYED)
  967. DECLARE_TASK(TASK_TALKER_HEADRESET)
  968. DECLARE_TASK(TASK_TALKER_STOPSHOOTING)
  969. DECLARE_TASK(TASK_TALKER_STARE)
  970. DECLARE_TASK(TASK_TALKER_LOOK_AT_CLIENT)
  971. DECLARE_TASK(TASK_TALKER_CLIENT_STARE)
  972. DECLARE_TASK(TASK_TALKER_EYECONTACT)
  973. DECLARE_TASK(TASK_TALKER_IDEALYAW)
  974. DECLARE_TASK(TASK_TALKER_WAIT_FOR_SEMAPHORE)
  975. //=========================================================
  976. // > SCHED_TALKER_IDLE_RESPONSE
  977. //=========================================================
  978. DEFINE_SCHEDULE
  979. (
  980. SCHED_TALKER_IDLE_RESPONSE,
  981. " Tasks"
  982. " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" // Stop and listen
  983. " TASK_WAIT 0.5" // Wait until sure it's me they are talking to
  984. " TASK_TALKER_IDEALYAW 0" // look at who I'm talking to
  985. " TASK_FACE_IDEAL 0"
  986. " TASK_TALKER_EYECONTACT 0" // Wait until speaker is done
  987. " TASK_TALKER_WAIT_FOR_SEMAPHORE 0"
  988. " TASK_TALKER_EYECONTACT 0" // Wait until speaker is done
  989. " TASK_TALKER_RESPOND 0" // Wait and then say my response
  990. " TASK_TALKER_IDEALYAW 0" // look at who I'm talking to
  991. " TASK_FACE_IDEAL 0"
  992. " TASK_SET_ACTIVITY ACTIVITY:ACT_SIGNAL3"
  993. " TASK_TALKER_EYECONTACT 0" // Wait until speaker is done
  994. ""
  995. " Interrupts"
  996. " COND_NEW_ENEMY"
  997. " COND_LIGHT_DAMAGE"
  998. " COND_HEAVY_DAMAGE"
  999. " COND_HEAR_DANGER"
  1000. " COND_HEAR_COMBAT"
  1001. " COND_PLAYER_PUSHING"
  1002. " COND_GIVE_WAY"
  1003. )
  1004. //=========================================================
  1005. // > SCHED_TALKER_IDLE_SPEAK
  1006. //=========================================================
  1007. DEFINE_SCHEDULE
  1008. (
  1009. SCHED_TALKER_IDLE_SPEAK,
  1010. " Tasks"
  1011. " TASK_TALKER_SPEAK 0" // question or remark
  1012. " TASK_TALKER_IDEALYAW 0" // look at who I'm talking to
  1013. " TASK_FACE_IDEAL 0"
  1014. " TASK_SET_ACTIVITY ACTIVITY:ACT_SIGNAL3"
  1015. " TASK_TALKER_EYECONTACT 0"
  1016. " TASK_WAIT_RANDOM 0.5"
  1017. ""
  1018. " Interrupts"
  1019. " COND_NEW_ENEMY"
  1020. " COND_LIGHT_DAMAGE"
  1021. " COND_HEAVY_DAMAGE"
  1022. " COND_HEAR_DANGER"
  1023. " COND_HEAR_COMBAT"
  1024. " COND_PLAYER_PUSHING"
  1025. " COND_GIVE_WAY"
  1026. )
  1027. //=========================================================
  1028. // > SCHED_TALKER_IDLE_HELLO
  1029. //=========================================================
  1030. DEFINE_SCHEDULE
  1031. (
  1032. SCHED_TALKER_IDLE_HELLO,
  1033. " Tasks"
  1034. " TASK_SET_ACTIVITY ACTIVITY:ACT_SIGNAL3" // Stop and talk
  1035. " TASK_TALKER_HELLO 0" // Try to say hello to player
  1036. " TASK_TALKER_EYECONTACT 0"
  1037. " TASK_WAIT 0.5" // wait a bit
  1038. " TASK_TALKER_HELLO 0" // Try to say hello to player
  1039. " TASK_TALKER_EYECONTACT 0"
  1040. " TASK_WAIT 0.5" // wait a bit
  1041. " TASK_TALKER_HELLO 0" // Try to say hello to player
  1042. " TASK_TALKER_EYECONTACT 0"
  1043. " TASK_WAIT 0.5" // wait a bit
  1044. " TASK_TALKER_HELLO 0" // Try to say hello to player
  1045. " TASK_TALKER_EYECONTACT 0"
  1046. " TASK_WAIT 0.5 " // wait a bit
  1047. ""
  1048. " Interrupts"
  1049. " COND_NEW_ENEMY"
  1050. " COND_LIGHT_DAMAGE"
  1051. " COND_HEAVY_DAMAGE"
  1052. " COND_PROVOKED"
  1053. " COND_HEAR_COMBAT"
  1054. " COND_HEAR_DANGER"
  1055. " COND_PLAYER_PUSHING"
  1056. " COND_GIVE_WAY"
  1057. )
  1058. //=========================================================
  1059. // > SCHED_TALKER_IDLE_STOP_SHOOTING
  1060. //=========================================================
  1061. DEFINE_SCHEDULE
  1062. (
  1063. SCHED_TALKER_IDLE_STOP_SHOOTING,
  1064. " Tasks"
  1065. " TASK_TALKER_STOPSHOOTING 0" // tell player to stop shooting friend
  1066. ""
  1067. " Interrupts"
  1068. " COND_NEW_ENEMY"
  1069. " COND_LIGHT_DAMAGE"
  1070. " COND_HEAVY_DAMAGE"
  1071. )
  1072. //=========================================================
  1073. // Scold the player before attacking.
  1074. //=========================================================
  1075. DEFINE_SCHEDULE
  1076. (
  1077. SCHED_TALKER_BETRAYED,
  1078. " Tasks"
  1079. " TASK_TALKER_BETRAYED 0"
  1080. " TASK_WAIT 0.5"
  1081. ""
  1082. " Interrupts"
  1083. " COND_HEAR_DANGER"
  1084. )
  1085. //=========================================================
  1086. // > SCHED_TALKER_IDLE_WATCH_CLIENT
  1087. //=========================================================
  1088. DEFINE_SCHEDULE
  1089. (
  1090. SCHED_TALKER_IDLE_WATCH_CLIENT,
  1091. " Tasks"
  1092. " TASK_STOP_MOVING 0"
  1093. " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE"
  1094. " TASK_TALKER_LOOK_AT_CLIENT 6"
  1095. ""
  1096. " Interrupts"
  1097. " COND_NEW_ENEMY"
  1098. " COND_LIGHT_DAMAGE"
  1099. " COND_HEAVY_DAMAGE"
  1100. " COND_PROVOKED"
  1101. " COND_HEAR_COMBAT" // sound flags - change these and you'll break the talking code.
  1102. " COND_HEAR_DANGER"
  1103. " COND_SMELL"
  1104. " COND_PLAYER_PUSHING"
  1105. " COND_TALKER_CLIENTUNSEEN"
  1106. " COND_GIVE_WAY"
  1107. " COND_IDLE_INTERRUPT"
  1108. )
  1109. //=========================================================
  1110. // > SCHED_TALKER_IDLE_WATCH_CLIENT_STARE
  1111. //=========================================================
  1112. DEFINE_SCHEDULE
  1113. (
  1114. SCHED_TALKER_IDLE_WATCH_CLIENT_STARE,
  1115. " Tasks"
  1116. " TASK_STOP_MOVING 0"
  1117. " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE"
  1118. " TASK_TALKER_CLIENT_STARE 6"
  1119. " TASK_TALKER_STARE 0"
  1120. " TASK_TALKER_IDEALYAW 0" // look at who I'm talking to
  1121. " TASK_FACE_IDEAL 0 "
  1122. " TASK_SET_ACTIVITY ACTIVITY:ACT_SIGNAL3"
  1123. " TASK_TALKER_EYECONTACT 0"
  1124. ""
  1125. " Interrupts"
  1126. " COND_NEW_ENEMY"
  1127. " COND_LIGHT_DAMAGE"
  1128. " COND_HEAVY_DAMAGE"
  1129. " COND_PROVOKED"
  1130. " COND_HEAR_COMBAT" // sound flags - change these and you'll break the talking code.
  1131. " COND_HEAR_DANGER"
  1132. " COND_SMELL"
  1133. " COND_PLAYER_PUSHING"
  1134. " COND_TALKER_CLIENTUNSEEN"
  1135. " COND_GIVE_WAY"
  1136. " COND_IDLE_INTERRUPT"
  1137. )
  1138. //=========================================================
  1139. // > SCHED_TALKER_IDLE_EYE_CONTACT
  1140. //=========================================================
  1141. DEFINE_SCHEDULE
  1142. (
  1143. SCHED_TALKER_IDLE_EYE_CONTACT,
  1144. " Tasks"
  1145. " TASK_TALKER_IDEALYAW 0" // look at who I'm talking to
  1146. " TASK_FACE_IDEAL 0"
  1147. " TASK_SET_ACTIVITY ACTIVITY:ACT_SIGNAL3"
  1148. " TASK_TALKER_EYECONTACT 0" // Wait until speaker is done
  1149. ""
  1150. " Interrupts"
  1151. " COND_NEW_ENEMY"
  1152. " COND_LIGHT_DAMAGE"
  1153. " COND_HEAVY_DAMAGE"
  1154. " COND_HEAR_DANGER"
  1155. " COND_HEAR_COMBAT"
  1156. " COND_PLAYER_PUSHING"
  1157. " COND_GIVE_WAY"
  1158. " COND_IDLE_INTERRUPT"
  1159. )
  1160. AI_END_CUSTOM_NPC()