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.
296 lines
8.4 KiB
296 lines
8.4 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//============================================================================= |
|
|
|
#include "cbase.h" |
|
#include "hintmessage.h" |
|
#include "hintsystem.h" |
|
|
|
#ifdef GAME_DLL |
|
#include "util.h" |
|
#endif |
|
|
|
//-------------------------------------------------------------------------------------------------------- |
|
/** |
|
* Simple utility function to allocate memory and duplicate a string |
|
*/ |
|
inline char *CloneString( const char *str ) |
|
{ |
|
char *cloneStr = new char [ strlen(str)+1 ]; |
|
strcpy( cloneStr, str ); |
|
return cloneStr; |
|
} |
|
|
|
extern int gmsgHudText; |
|
|
|
enum { HMQ_SIZE = 8 }; // Maximum number of messages queue can hold |
|
// If the limit is reached, no more can be |
|
// added. |
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
CHintMessage::CHintMessage( const char * hintString, CUtlVector< const char * > * args, float duration ) |
|
{ |
|
m_hintString = hintString; |
|
m_duration = duration; |
|
|
|
if ( args ) |
|
{ |
|
for ( int i=0; i<args->Count(); ++i ) |
|
{ |
|
m_args.AddToTail( CloneString( (*args)[i] ) ); |
|
} |
|
} |
|
} |
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
CHintMessage::~CHintMessage() |
|
{ |
|
for ( int i=0; i<m_args.Count(); ++i ) |
|
{ |
|
delete[] m_args[i]; |
|
} |
|
m_args.RemoveAll(); |
|
} |
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
bool CHintMessage::IsEquivalent( const char *hintString, CUtlVector< const char * > * args ) const |
|
{ |
|
if ( FStrEq( hintString, m_hintString ) ) |
|
{ |
|
if ( !args && !m_args.Count() ) |
|
{ |
|
return true; |
|
} |
|
|
|
if ( !args ) |
|
return false; |
|
|
|
if ( args->Count() != m_args.Count() ) |
|
return false; |
|
|
|
for ( int i=0; i<args->Count(); ++i ) |
|
{ |
|
if ( !FStrEq( (*args)[i], m_args[i] ) ) |
|
{ |
|
return false; |
|
} |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
void CHintMessage::Send( CBasePlayer * client ) |
|
{ |
|
if ( !client ) |
|
return; |
|
|
|
#ifdef GAME_DLL |
|
// Custom hint text sending to allow for arguments. This is OK because the client has a custom |
|
// message parser for hint text that can read the arguments. |
|
CSingleUserRecipientFilter user( (CBasePlayer *)client ); |
|
user.MakeReliable(); |
|
|
|
// client can handle 1 string only |
|
UserMessageBegin( user, "HintText" ); |
|
WRITE_STRING( m_hintString ); |
|
MessageEnd(); |
|
#endif |
|
} |
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
CHintMessageQueue::CHintMessageQueue( CBasePlayer *pPlayer ) |
|
{ |
|
m_pPlayer = pPlayer; |
|
} |
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
void CHintMessageQueue::Reset() |
|
{ |
|
m_tmMessageEnd = 0; |
|
for ( int i=0; i<m_messages.Count(); ++i ) |
|
{ |
|
delete m_messages[i]; |
|
} |
|
m_messages.RemoveAll(); |
|
} |
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
void CHintMessageQueue::Update() |
|
{ |
|
if ( !m_pPlayer ) |
|
return; |
|
|
|
// test this - send the message as soon as it is ready, |
|
// just stomp the old message |
|
//if ( gpGlobals->curtime > m_tmMessageEnd ) |
|
{ |
|
if ( m_messages.Count() ) |
|
{ |
|
CHintMessage *msg = m_messages[0]; |
|
m_tmMessageEnd = gpGlobals->curtime + msg->GetDuration(); |
|
msg->Send( m_pPlayer ); |
|
delete msg; |
|
m_messages.Remove( 0 ); |
|
} |
|
} |
|
} |
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
bool CHintMessageQueue::AddMessage( const char* message, float duration, CUtlVector< const char * > * args ) |
|
{ |
|
if ( !m_pPlayer ) |
|
return false; |
|
|
|
for ( int i=0; i<m_messages.Count(); ++i ) |
|
{ |
|
// weed out duplicates |
|
if ( m_messages[i]->IsEquivalent( message, args ) ) |
|
{ |
|
return true; |
|
} |
|
} |
|
|
|
// 'message' is not copied, so the pointer must remain valid forever |
|
CHintMessage *msg = new CHintMessage( message, args, duration ); |
|
m_messages.AddToTail( msg ); |
|
return true; |
|
} |
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *pPlayer - |
|
//----------------------------------------------------------------------------- |
|
CHintMessageTimers::CHintMessageTimers( CHintSystem *pSystem, CHintMessageQueue *pQueue ) |
|
{ |
|
m_pHintSystem = pSystem; |
|
m_pQueue = pQueue; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Clear out all registered timers |
|
//----------------------------------------------------------------------------- |
|
void CHintMessageTimers::Reset() |
|
{ |
|
for ( int i=0; i<m_Timers.Count(); ++i ) |
|
{ |
|
delete m_Timers[i]; |
|
} |
|
m_Timers.RemoveAll(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Check & fire any timers that should fire based on their duration. |
|
//----------------------------------------------------------------------------- |
|
void CHintMessageTimers::Update() |
|
{ |
|
if ( !m_pHintSystem ) |
|
return; |
|
|
|
for ( int i = 0; i < m_Timers.Count(); i++ ) |
|
{ |
|
if ( m_Timers[i]->timer.Expired() ) |
|
{ |
|
if ( m_pHintSystem->TimerShouldFire( m_Timers[i]->iHintID ) ) |
|
{ |
|
//Warning("TIMER FIRED: %s\n", m_pszHintMessages[m_Timers[i]->iHintID] ); |
|
|
|
m_pHintSystem->HintMessage( m_Timers[i]->iHintID ); |
|
|
|
// Remove and return. No reason to bring up multiple hints. |
|
RemoveTimer( m_Timers[i]->iHintID ); |
|
return; |
|
} |
|
else |
|
{ |
|
// Push the timer out again |
|
m_Timers[i]->timer.Start(); |
|
} |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Register a new timer that the system should should keep track of. |
|
// Input : iHintID - The ID of the hint message |
|
// timer_duration - the total time the timer should run for until it fires the hint message |
|
// message_duration - the duration passed into the hint message system when the hint fires |
|
// args - the arguments passed into the hint message system when the hint fires |
|
//----------------------------------------------------------------------------- |
|
void CHintMessageTimers::AddTimer( int iHintID, float timer_duration, float message_duration, CUtlVector< const char * > * args ) |
|
{ |
|
if ( GetTimerIndex(iHintID) != m_Timers.InvalidIndex() ) |
|
return; |
|
|
|
// 'message' is not copied, so the pointer must remain valid forever |
|
hintmessagetime_t *newTimer = new hintmessagetime_t( timer_duration ); |
|
newTimer->iHintID = iHintID; |
|
newTimer->flMessageDuration = message_duration; |
|
if ( args ) |
|
{ |
|
for ( int i=0; i<args->Count(); ++i ) |
|
{ |
|
newTimer->args.AddToTail( CloneString( (*args)[i] ) ); |
|
} |
|
} |
|
m_Timers.AddToTail( newTimer ); |
|
|
|
//Warning("TIMER ADDED: %s\n", m_pszHintMessages[iHintID] ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CHintMessageTimers::RemoveTimer( int iHintID ) |
|
{ |
|
int iIndex = GetTimerIndex(iHintID); |
|
if ( iIndex != m_Timers.InvalidIndex() ) |
|
{ |
|
//Warning("TIMER REMOVED: %s\n", m_pszHintMessages[iHintID] ); |
|
m_Timers.Remove( iIndex ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CHintMessageTimers::StartTimer( int iHintID ) |
|
{ |
|
int iIndex = GetTimerIndex(iHintID); |
|
if ( iIndex != m_Timers.InvalidIndex() ) |
|
{ |
|
//Warning("TIMER STARTED: %s\n", m_pszHintMessages[iHintID] ); |
|
m_Timers[iIndex]->timer.Start(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CHintMessageTimers::StopTimer( int iHintID ) |
|
{ |
|
int iIndex = GetTimerIndex(iHintID); |
|
if ( iIndex != m_Timers.InvalidIndex() ) |
|
{ |
|
//Warning("TIMER STOPPED: %s\n", m_pszHintMessages[iHintID] ); |
|
m_Timers[iIndex]->timer.Stop(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Return the index of the hint message in the timer list, if any |
|
//----------------------------------------------------------------------------- |
|
int CHintMessageTimers::GetTimerIndex( int iHintID ) |
|
{ |
|
for ( int i = 0; i < m_Timers.Count(); i++ ) |
|
{ |
|
if ( m_Timers[i]->iHintID == iHintID ) |
|
return i; |
|
} |
|
|
|
return m_Timers.InvalidIndex(); |
|
}
|
|
|