📄 vox.cpp
字号:
memcpy( tempBuffer + tempBufferPos, pSentenceData, length );
// Move the copy position
tempBufferPos += length;
pSentenceData = pNext;
// Skip ahead of the opening brace
if ( *pSentenceData )
pSentenceData++;
// Skip whitespace
while ( *pSentenceData && *pSentenceData <= 32 )
pSentenceData++;
// Simple comparison of string commands:
switch( tolower(*pSentenceData) )
{
case 'l':
// All commands starting with the letter 'l' here
if ( !strnicmp( pSentenceData, "len", 3 ) )
{
g_Sentences[sentenceIndex].length = atof( pSentenceData + 3 ) ;
}
break;
case 0:
default:
break;
}
pSentenceData = ScanForwardUntil( pSentenceData, '}' );
// Skip the closing brace
if ( *pSentenceData )
pSentenceData++;
// Skip trailing whitespace
while ( *pSentenceData && *pSentenceData <= 32 )
pSentenceData++;
}
if ( tempBufferPos < sizeof(tempBuffer) )
{
// terminate cleaned up copy
tempBuffer[ tempBufferPos ] = 0;
// Copy it over the original data
strcpy( pStart, tempBuffer );
}
}
#define CSENTENCE_LRU_MAX 32
struct sentencegroup_t
{
char szgroupname[CVOXSENTENCEMAX];
int count;
unsigned char rgblru[CSENTENCE_LRU_MAX];
};
CUtlVector<sentencegroup_t> g_SentenceGroups;
//-----------------------------------------------------------------------------
// Purpose: Add a new group or increment count of the existing one
// Input : *pSentenceName - text of the sentence name
//-----------------------------------------------------------------------------
void VOX_GroupAdd( const char *pSentenceName )
{
int len = strlen( pSentenceName ) - 1;
char groupName[CVOXSENTENCEMAX];
// group members end in a number
if ( len <= 0 || !isdigit(pSentenceName[len]) )
return;
// truncate away the index
while ( len > 0 && isdigit(pSentenceName[len]) )
len--;
if ( len > sizeof(groupName)-1 )
{
Msg( "Group %s name too long (%d chars max)\n", pSentenceName, sizeof(groupName)-1 );
return;
}
// make a copy of the actual group name
Q_strncpy( groupName, pSentenceName, len+2 );
// check for it in the list
int i;
sentencegroup_t *pGroup;
int groupCount = g_SentenceGroups.Size();
for ( i = 0; i < groupCount; i++ )
{
int groupIndex = (i + groupCount-1) % groupCount;
// Start at the last group a loop around
pGroup = &g_SentenceGroups[groupIndex];
if ( !strcmp( pGroup->szgroupname, groupName ) )
{
// Matches previous group, bump count
pGroup->count++;
return;
}
}
// new group
int addIndex = g_SentenceGroups.AddToTail();
sentencegroup_t *group = &g_SentenceGroups[addIndex];
strcpy( group->szgroupname, groupName );
group->count = 1;
}
#if DEAD
//-----------------------------------------------------------------------------
// Purpose: clear the sentence groups
//-----------------------------------------------------------------------------
void VOX_GroupClear( void )
{
g_SentenceGroups.RemoveAll();
}
#endif
void VOX_LRUInit( sentencegroup_t *pGroup )
{
int i, n1, n2, temp;
if ( pGroup->count )
{
if (pGroup->count > CSENTENCE_LRU_MAX)
pGroup->count = CSENTENCE_LRU_MAX;
for (i = 0; i < pGroup->count; i++)
pGroup->rgblru[i] = (unsigned char) i;
// randomize array by swapping random elements
for (i = 0; i < (pGroup->count * 4); i++)
{
// FIXME: This should probably call through g_pSoundServices
// or some other such call?
n1 = RandomInt(0,pGroup->count-1);
n2 = RandomInt(0,pGroup->count-1);
temp = pGroup->rgblru[n1];
pGroup->rgblru[n1] = pGroup->rgblru[n2];
pGroup->rgblru[n2] = temp;
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Init the LRU for each sentence group
//-----------------------------------------------------------------------------
void VOX_GroupInitAllLRUs( void )
{
int i;
for ( i = 0; i < g_SentenceGroups.Size(); i++ )
{
VOX_LRUInit( &g_SentenceGroups[i] );
}
}
//-----------------------------------------------------------------------------
// Purpose: Given a group name, return that group's index
// Input : *pGroupName - name of the group
// Output : int - index in group table, returns -1 if no matching group is found
//-----------------------------------------------------------------------------
int VOX_GroupIndexFromName( const char *pGroupName )
{
int i;
if ( pGroupName )
{
// search rgsentenceg for match on szgroupname
for ( i = 0; i < g_SentenceGroups.Size(); i++ )
{
if ( !strcmp( g_SentenceGroups[i].szgroupname, pGroupName ) )
return i;
}
}
return -1;
}
//-----------------------------------------------------------------------------
// Purpose: return the group's name
// Input : groupIndex - index of the group
// Output : const char * - name pointer
//-----------------------------------------------------------------------------
const char *VOX_GroupNameFromIndex( int groupIndex )
{
if ( groupIndex >= 0 && groupIndex < g_SentenceGroups.Size() )
return g_SentenceGroups[groupIndex].szgroupname;
return NULL;
}
// ignore lru. pick next sentence from sentence group. Go in order until we hit the last sentence,
// then repeat list if freset is true. If freset is false, then repeat last sentence.
// ipick is passed in as the requested sentence ordinal.
// ipick 'next' is returned.
// return of -1 indicates an error.
int VOX_GroupPickSequential( int isentenceg, char *szfound, int szfoundLen, int ipick, int freset )
{
char *szgroupname;
unsigned char count;
if (isentenceg < 0 || isentenceg > g_SentenceGroups.Size())
return -1;
szgroupname = g_SentenceGroups[isentenceg].szgroupname;
count = g_SentenceGroups[isentenceg].count;
if (count == 0)
return -1;
if (ipick >= count)
ipick = count-1;
Q_snprintf( szfound, szfoundLen, "!%s%d", szgroupname, ipick );
if (ipick >= count)
{
if (freset)
// reset at end of list
return 0;
else
return count;
}
return ipick + 1;
}
// pick a random sentence from rootname0 to rootnameX.
// picks from the rgsentenceg[isentenceg] least
// recently used, modifies lru array. returns the sentencename.
// note, lru must be seeded with 0-n randomized sentence numbers, with the
// rest of the lru filled with -1. The first integer in the lru is
// actually the size of the list. Returns ipick, the ordinal
// of the picked sentence within the group.
int VOX_GroupPick( int isentenceg, char *szfound, int strLen )
{
char *szgroupname;
unsigned char *plru;
unsigned char i;
unsigned char count;
unsigned char ipick=0;
int ffound = FALSE;
if (isentenceg < 0 || isentenceg > g_SentenceGroups.Size())
return -1;
szgroupname = g_SentenceGroups[isentenceg].szgroupname;
count = g_SentenceGroups[isentenceg].count;
plru = g_SentenceGroups[isentenceg].rgblru;
while (!ffound)
{
for (i = 0; i < count; i++)
if (plru[i] != 0xFF)
{
ipick = plru[i];
plru[i] = 0xFF;
ffound = TRUE;
break;
}
if (!ffound)
{
VOX_LRUInit( &g_SentenceGroups[isentenceg] );
}
else
{
Q_snprintf( szfound, strLen, "!%s%d", szgroupname, ipick );
return ipick;
}
}
return -1;
}
typedef struct filelist_s filelist_t;
struct filelist_s
{
const char *pFileName;
byte *pFileData;
filelist_t *pNext;
};
static filelist_t *g_pSentenceFileList = NULL;
//-----------------------------------------------------------------------------
// Purpose: clear / reinitialize the vox list
//-----------------------------------------------------------------------------
void VOX_ListClear( void )
{
filelist_t *pList, *pNext;
pList = g_pSentenceFileList;
while ( pList )
{
pNext = pList->pNext;
COM_FreeFile( pList->pFileData );
free( pList );
pList = pNext;
}
g_pSentenceFileList = NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Check to see if this file is in the list
// Input : *psentenceFileName -
// Output : int, true if the file is in the list, false if not
//-----------------------------------------------------------------------------
int VOX_ListFileIsLoaded( const char *psentenceFileName )
{
filelist_t *pList = g_pSentenceFileList;
while ( pList )
{
if ( !strcmp( psentenceFileName, pList->pFileName ) )
return true;
pList = pList->pNext;
}
return false;
}
//-----------------------------------------------------------------------------
// Purpose: Add this file name to the sentence list
// Input : *psentenceFileName -
//-----------------------------------------------------------------------------
void VOX_ListMarkFileLoaded( const char *psentenceFileName, byte *pFileData )
{
filelist_t *pEntry;
char *pName;
pEntry = (filelist_t *)malloc( sizeof(filelist_t) + strlen( psentenceFileName ) + 1);
if ( pEntry )
{
pName = (char *)(pEntry+1);
strcpy( pName, psentenceFileName );
pEntry->pFileName = pName;
pEntry->pFileData = pFileData;
pEntry->pNext = g_pSentenceFileList;
g_pSentenceFileList = pEntry;
}
}
// Load sentence file into memory, insert null terminators to
// delimit sentence name/sentence pairs. Keep pointer to each
// sentence name so we can search later.
void VOX_ReadSentenceFile( const char *psentenceFileName )
{
char *pch, *pFileData;
int fileSize;
char c;
char *pchlast, *pSentenceData;
characterset_t whitespace;
// Have we already loaded this file?
if ( VOX_ListFileIsLoaded( psentenceFileName ) )
return;
// load file
// USES malloc()
pFileData = (char*)COM_LoadFileForMe( psentenceFileName, &fileSize );
if (!pFileData)
{
DevMsg ("Couldn't load %s\n", psentenceFileName);
return;
}
pch = pFileData;
pchlast = pch + fileSize;
CharacterSetBuild( &whitespace, "\n\r\t " );
while (pch < pchlast)
{
// Only process this pass on sentences
pSentenceData = NULL;
// skip newline, cr, tab, space
c = *pch;
while (pch < pchlast && IN_CHARACTERSET( whitespace, c ))
c = *(++pch);
// skip entire line if first char is /
if (*pch != '/')
{
int addIndex = g_Sentences.AddToTail();
sentence_t *pSentence = &g_Sentences[addIndex];
pSentence->pName = pch;
pSentence->length = 0;
// scan forward to first space, insert null terminator
// after sentence name
c = *pch;
while (pch < pchlast && c != ' ')
c = *(++pch);
if (pch < pchlast)
*pch++ = 0;
// A sentence may have some line commands, make an extra pass
pSentenceData = pch;
}
// scan forward to end of sentence or eof
while (pch < pchlast && pch[0] != '\n' && pch[0] != '\r')
pch++;
// insert null terminator
if (pch < pchlast)
*pch++ = 0;
// If we have some sentence data, parse out any line commands
if ( pSentenceData && pSentenceData < pchlast )
{
int index = g_Sentences.Size()-1;
// The current sentence has an index of count-1
VOX_ParseLineCommands( pSentenceData, index );
// Add a new group or increment count of the existing one
VOX_GroupAdd( g_Sentences[index].pName );
}
}
VOX_GroupInitAllLRUs();
VOX_ListMarkFileLoaded( psentenceFileName, (unsigned char*)pFileData );
}
//-----------------------------------------------------------------------------
// Purpose: Get the current number of sentences in the database
// Output : int
//-----------------------------------------------------------------------------
int VOX_SentenceCount( void )
{
return g_Sentences.Size();
}
float VOX_SentenceLength( int sentence_num )
{
if ( sentence_num < 0 || sentence_num > g_Sentences.Size()-1 )
return 0.0f;
return g_Sentences[ sentence_num ].length;
}
// scan g_Sentences, looking for pszin sentence name
// return pointer to sentence data if found, null if not
// CONSIDER: if we have a large number of sentences, should
// CONSIDER: sort strings in g_Sentences and do binary search.
char *VOX_LookupString(const char *pSentenceName, int *psentencenum)
{
int i;
for (i = 0; i < g_Sentences.Size(); i++)
{
if (!stricmp(pSentenceName, g_Sentences[i].pName))
{
if (psentencenum)
*psentencenum = i;
return (g_Sentences[i].pName + strlen(g_Sentences[i].pName) + 1);
}
}
return NULL;
}
// Abstraction for sentence name array
const char *VOX_SentenceNameFromIndex( int sentencenum )
{
if ( sentencenum < g_Sentences.Size() )
return g_Sentences[sentencenum].pName;
return NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -