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.

211 lines
6.1 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "ai_sentence.h"
  9. #include "ai_squad.h"
  10. // memdbgon must be the last include file in a .cpp file!!!
  11. #include "tier0/memdbgon.h"
  12. ConVar npc_sentences( "npc_sentences", "0" );
  13. //-----------------------------------------------------------------------------
  14. // Save/load
  15. //-----------------------------------------------------------------------------
  16. BEGIN_SIMPLE_DATADESC(CAI_SentenceBase)
  17. DEFINE_FIELD( m_voicePitch, FIELD_INTEGER ),
  18. DEFINE_FIELD( m_nQueuedSentenceIndex, FIELD_INTEGER ),
  19. DEFINE_FIELD( m_flQueueTimeout, FIELD_TIME ),
  20. DEFINE_FIELD( m_nQueueSoundPriority, FIELD_INTEGER ),
  21. END_DATADESC();
  22. //-----------------------------------------------------------------------------
  23. // Speech
  24. //-----------------------------------------------------------------------------
  25. CAI_SentenceBase::CAI_SentenceBase()
  26. {
  27. ClearQueue();
  28. }
  29. //-----------------------------------------------------------------------------
  30. // Debug output
  31. //-----------------------------------------------------------------------------
  32. void CAI_SentenceBase::SentenceMsg( const char *pStatus, const char *pSentence )
  33. {
  34. int nMode = npc_sentences.GetInt();
  35. switch( nMode )
  36. {
  37. case 0:
  38. return;
  39. case 1:
  40. DevMsg( "SENTENCE [%d %.2f] %s: %s\n", GetOuter()->entindex(), gpGlobals->curtime, pStatus, pSentence );
  41. break;
  42. case 2:
  43. DevMsg( GetOuter(), "SENTENCE [%d %.2f] %s: %s\n", GetOuter()->entindex(), gpGlobals->curtime, pStatus, pSentence );
  44. break;
  45. }
  46. }
  47. //-----------------------------------------------------------------------------
  48. // Check for queued-up-sentences + speak them
  49. //-----------------------------------------------------------------------------
  50. void CAI_SentenceBase::ClearQueue()
  51. {
  52. m_nQueuedSentenceIndex = -1;
  53. }
  54. //-----------------------------------------------------------------------------
  55. // Check for queued-up-sentences + speak them
  56. //-----------------------------------------------------------------------------
  57. void CAI_SentenceBase::UpdateSentenceQueue()
  58. {
  59. if ( m_nQueuedSentenceIndex == -1 )
  60. return;
  61. // Check for timeout
  62. if ( m_flQueueTimeout < gpGlobals->curtime )
  63. {
  64. ClearQueue();
  65. return;
  66. }
  67. if ( GetOuter()->FOkToMakeSound( m_nQueueSoundPriority ) )
  68. {
  69. SENTENCEG_PlaySentenceIndex( GetOuter()->edict(), m_nQueuedSentenceIndex, GetVolume(), GetSoundLevel(), 0, GetVoicePitch() );
  70. const char *pSentenceName = engine->SentenceNameFromIndex( m_nQueuedSentenceIndex );
  71. SentenceMsg( "Speaking [from QUEUE]", pSentenceName );
  72. GetOuter()->JustMadeSound( m_nQueueSoundPriority );
  73. ClearQueue();
  74. }
  75. }
  76. //-----------------------------------------------------------------------------
  77. // Speech criteria
  78. //-----------------------------------------------------------------------------
  79. bool CAI_SentenceBase::MatchesCriteria( SentenceCriteria_t nCriteria )
  80. {
  81. switch( nCriteria )
  82. {
  83. case SENTENCE_CRITERIA_ALWAYS:
  84. return true;
  85. case SENTENCE_CRITERIA_NORMAL:
  86. return (GetOuter()->GetState() == NPC_STATE_COMBAT) || (GetOuter()->HasSpawnFlags( SF_NPC_GAG ) == 0);
  87. case SENTENCE_CRITERIA_IN_SQUAD:
  88. if ( (GetOuter()->GetState() != NPC_STATE_COMBAT) && GetOuter()->HasSpawnFlags( SF_NPC_GAG ) )
  89. return false;
  90. return GetOuter()->GetSquad() && (GetOuter()->GetSquad()->NumMembers() > 1);
  91. case SENTENCE_CRITERIA_SQUAD_LEADER:
  92. {
  93. if ( (GetOuter()->GetState() != NPC_STATE_COMBAT) && GetOuter()->HasSpawnFlags( SF_NPC_GAG ) )
  94. return false;
  95. CAI_Squad *pSquad = GetOuter()->GetSquad();
  96. return pSquad && (pSquad->NumMembers() > 1) && pSquad->IsLeader( GetOuter() );
  97. }
  98. }
  99. return true;
  100. }
  101. //-----------------------------------------------------------------------------
  102. // Play the actual sentence
  103. //-----------------------------------------------------------------------------
  104. int CAI_SentenceBase::PlaySentence( const char *pSentence )
  105. {
  106. int nSentenceIndex = SENTENCEG_PlayRndSz( GetOuter()->edict(), pSentence, GetVolume(), GetSoundLevel(), 0, GetVoicePitch());
  107. if ( nSentenceIndex < 0 )
  108. {
  109. SentenceMsg( "BOGUS", pSentence );
  110. return -1;
  111. }
  112. const char *pSentenceName = engine->SentenceNameFromIndex( nSentenceIndex );
  113. SentenceMsg( "Speaking", pSentenceName );
  114. return nSentenceIndex;
  115. }
  116. //-----------------------------------------------------------------------------
  117. // Speech
  118. //-----------------------------------------------------------------------------
  119. int CAI_SentenceBase::Speak( const char *pSentence, SentencePriority_t nSoundPriority, SentenceCriteria_t nCriteria )
  120. {
  121. if ( !MatchesCriteria(nCriteria) )
  122. return -1;
  123. // Speaking clears the queue
  124. ClearQueue();
  125. if ( nSoundPriority == SENTENCE_PRIORITY_INVALID )
  126. {
  127. return PlaySentence( pSentence );
  128. }
  129. int nSentenceIndex = -1;
  130. if ( GetOuter()->FOkToMakeSound( nSoundPriority ) )
  131. {
  132. nSentenceIndex = PlaySentence( pSentence );
  133. // Make sure sentence length utility works
  134. // float flSentenceTime = enginesound->GetSoundDuration( nSentenceIndex );
  135. GetOuter()->JustMadeSound( nSoundPriority, 2.0f /*flSentenceTime*/ );
  136. }
  137. else
  138. {
  139. SentenceMsg( "CULL", pSentence );
  140. }
  141. return nSentenceIndex;
  142. }
  143. //-----------------------------------------------------------------------------
  144. // Speech w/ queue
  145. //-----------------------------------------------------------------------------
  146. int CAI_SentenceBase::SpeakQueued( const char *pSentence, SentencePriority_t nSoundPriority, SentenceCriteria_t nCriteria )
  147. {
  148. if ( !MatchesCriteria(nCriteria) )
  149. return -1;
  150. // Speaking clears the queue
  151. ClearQueue();
  152. int nSentenceIndex = Speak( pSentence, nSoundPriority, nCriteria );
  153. if ( nSentenceIndex >= 0 )
  154. return nSentenceIndex;
  155. // Queue up the sentence for later playing
  156. int nQueuedSentenceIndex = SENTENCEG_PickRndSz( pSentence );
  157. if ( nQueuedSentenceIndex == -1 )
  158. return -1;
  159. int nSquadCount = GetOuter()->GetSquad() ? GetOuter()->GetSquad()->NumMembers() : 1;
  160. m_flQueueTimeout = gpGlobals->curtime + nSquadCount * 2.0f;
  161. m_nQueueSoundPriority = nSoundPriority;
  162. m_nQueuedSentenceIndex = nQueuedSentenceIndex;
  163. return -1;
  164. }