212 lines
6.3 KiB
C++
212 lines
6.3 KiB
C++
|
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
|||
|
//
|
|||
|
// Purpose:
|
|||
|
//
|
|||
|
// $NoKeywords: $
|
|||
|
//=============================================================================//
|
|||
|
|
|||
|
#include "cbase.h"
|
|||
|
#include "ai_sentence.h"
|
|||
|
#include "ai_squad.h"
|
|||
|
|
|||
|
// memdbgon must be the last include file in a .cpp file!!!
|
|||
|
#include "tier0/memdbgon.h"
|
|||
|
|
|||
|
ConVar npc_sentences( "npc_sentences", "0" );
|
|||
|
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Save/load
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
BEGIN_SIMPLE_DATADESC(CAI_SentenceBase)
|
|||
|
DEFINE_FIELD( m_voicePitch, FIELD_INTEGER ),
|
|||
|
DEFINE_FIELD( m_nQueuedSentenceIndex, FIELD_INTEGER ),
|
|||
|
DEFINE_FIELD( m_flQueueTimeout, FIELD_TIME ),
|
|||
|
DEFINE_FIELD( m_nQueueSoundPriority, FIELD_INTEGER ),
|
|||
|
END_DATADESC();
|
|||
|
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Speech
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
CAI_SentenceBase::CAI_SentenceBase()
|
|||
|
{
|
|||
|
ClearQueue();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Debug output
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
void CAI_SentenceBase::SentenceMsg( const char *pStatus, const char *pSentence )
|
|||
|
{
|
|||
|
int nMode = npc_sentences.GetInt();
|
|||
|
switch( nMode )
|
|||
|
{
|
|||
|
case 0:
|
|||
|
return;
|
|||
|
|
|||
|
case 1:
|
|||
|
DevMsg( "SENTENCE [%d %.2f] %s: %s\n", GetOuter()->entindex(), gpGlobals->curtime, pStatus, pSentence );
|
|||
|
break;
|
|||
|
|
|||
|
case 2:
|
|||
|
DevMsg( GetOuter(), "SENTENCE [%d %.2f] %s: %s\n", GetOuter()->entindex(), gpGlobals->curtime, pStatus, pSentence );
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Check for queued-up-sentences + speak them
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
void CAI_SentenceBase::ClearQueue()
|
|||
|
{
|
|||
|
m_nQueuedSentenceIndex = -1;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Check for queued-up-sentences + speak them
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
void CAI_SentenceBase::UpdateSentenceQueue()
|
|||
|
{
|
|||
|
if ( m_nQueuedSentenceIndex == -1 )
|
|||
|
return;
|
|||
|
|
|||
|
// Check for timeout
|
|||
|
if ( m_flQueueTimeout < gpGlobals->curtime )
|
|||
|
{
|
|||
|
ClearQueue();
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if ( GetOuter()->FOkToMakeSound( m_nQueueSoundPriority ) )
|
|||
|
{
|
|||
|
SENTENCEG_PlaySentenceIndex( GetOuter()->edict(), m_nQueuedSentenceIndex, GetVolume(), GetSoundLevel(), 0, GetVoicePitch() );
|
|||
|
|
|||
|
const char *pSentenceName = engine->SentenceNameFromIndex( m_nQueuedSentenceIndex );
|
|||
|
SentenceMsg( "Speaking [from QUEUE]", pSentenceName );
|
|||
|
|
|||
|
GetOuter()->JustMadeSound( m_nQueueSoundPriority );
|
|||
|
ClearQueue();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Speech criteria
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
bool CAI_SentenceBase::MatchesCriteria( SentenceCriteria_t nCriteria )
|
|||
|
{
|
|||
|
switch( nCriteria )
|
|||
|
{
|
|||
|
case SENTENCE_CRITERIA_ALWAYS:
|
|||
|
return true;
|
|||
|
|
|||
|
case SENTENCE_CRITERIA_NORMAL:
|
|||
|
return (GetOuter()->GetState() == NPC_STATE_COMBAT) || (GetOuter()->HasSpawnFlags( SF_NPC_GAG ) == 0);
|
|||
|
|
|||
|
case SENTENCE_CRITERIA_IN_SQUAD:
|
|||
|
if ( (GetOuter()->GetState() != NPC_STATE_COMBAT) && GetOuter()->HasSpawnFlags( SF_NPC_GAG ) )
|
|||
|
return false;
|
|||
|
return GetOuter()->GetSquad() && (GetOuter()->GetSquad()->NumMembers() > 1);
|
|||
|
|
|||
|
case SENTENCE_CRITERIA_SQUAD_LEADER:
|
|||
|
{
|
|||
|
if ( (GetOuter()->GetState() != NPC_STATE_COMBAT) && GetOuter()->HasSpawnFlags( SF_NPC_GAG ) )
|
|||
|
return false;
|
|||
|
|
|||
|
CAI_Squad *pSquad = GetOuter()->GetSquad();
|
|||
|
return pSquad && (pSquad->NumMembers() > 1) && pSquad->IsLeader( GetOuter() );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Play the actual sentence
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
int CAI_SentenceBase::PlaySentence( const char *pSentence )
|
|||
|
{
|
|||
|
int nSentenceIndex = SENTENCEG_PlayRndSz( GetOuter()->edict(), pSentence, GetVolume(), GetSoundLevel(), 0, GetVoicePitch());
|
|||
|
if ( nSentenceIndex < 0 )
|
|||
|
{
|
|||
|
SentenceMsg( "BOGUS", pSentence );
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
const char *pSentenceName = engine->SentenceNameFromIndex( nSentenceIndex );
|
|||
|
SentenceMsg( "Speaking", pSentenceName );
|
|||
|
return nSentenceIndex;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Speech
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
int CAI_SentenceBase::Speak( const char *pSentence, SentencePriority_t nSoundPriority, SentenceCriteria_t nCriteria )
|
|||
|
{
|
|||
|
if ( !MatchesCriteria(nCriteria) )
|
|||
|
return -1;
|
|||
|
|
|||
|
// Speaking clears the queue
|
|||
|
ClearQueue();
|
|||
|
|
|||
|
if ( nSoundPriority == SENTENCE_PRIORITY_INVALID )
|
|||
|
{
|
|||
|
return PlaySentence( pSentence );
|
|||
|
}
|
|||
|
|
|||
|
int nSentenceIndex = -1;
|
|||
|
if ( GetOuter()->FOkToMakeSound( nSoundPriority ) )
|
|||
|
{
|
|||
|
nSentenceIndex = PlaySentence( pSentence );
|
|||
|
|
|||
|
// Make sure sentence length utility works
|
|||
|
// float flSentenceTime = enginesound->GetSoundDuration( nSentenceIndex );
|
|||
|
GetOuter()->JustMadeSound( nSoundPriority, 2.0f /*flSentenceTime*/ );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
SentenceMsg( "CULL", pSentence );
|
|||
|
}
|
|||
|
|
|||
|
return nSentenceIndex;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Speech w/ queue
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
int CAI_SentenceBase::SpeakQueued( const char *pSentence, SentencePriority_t nSoundPriority, SentenceCriteria_t nCriteria )
|
|||
|
{
|
|||
|
if ( !MatchesCriteria(nCriteria) )
|
|||
|
return -1;
|
|||
|
|
|||
|
// Speaking clears the queue
|
|||
|
ClearQueue();
|
|||
|
|
|||
|
int nSentenceIndex = Speak( pSentence, nSoundPriority, nCriteria );
|
|||
|
if ( nSentenceIndex >= 0 )
|
|||
|
return nSentenceIndex;
|
|||
|
|
|||
|
// Queue up the sentence for later playing
|
|||
|
int nQueuedSentenceIndex = SENTENCEG_PickRndSz( pSentence );
|
|||
|
if ( nQueuedSentenceIndex == -1 )
|
|||
|
return -1;
|
|||
|
|
|||
|
int nSquadCount = GetOuter()->GetSquad() ? GetOuter()->GetSquad()->NumMembers() : 1;
|
|||
|
m_flQueueTimeout = gpGlobals->curtime + nSquadCount * 2.0f;
|
|||
|
m_nQueueSoundPriority = nSoundPriority;
|
|||
|
m_nQueuedSentenceIndex = nQueuedSentenceIndex;
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|