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.
303 lines
8.5 KiB
303 lines
8.5 KiB
//====== Copyright © 1996-2004, Valve Corporation, All rights reserved. =======
|
|
//
|
|
// Purpose:
|
|
//
|
|
//=============================================================================
|
|
|
|
#include "cbase.h"
|
|
#include "hintmessage.h"
|
|
#include "hintsystem.h"
|
|
#include "usermessages.h"
|
|
|
|
#ifdef GAME_DLL
|
|
#include "util.h"
|
|
#endif
|
|
|
|
// NOTE: This has to be the last file included!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------------
|
|
/**
|
|
* 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
|
|
CCSUsrMsg_HintText msg;
|
|
msg.set_text( m_hintString );
|
|
|
|
SendUserMessage( user, CS_UM_HintText, msg );
|
|
|
|
#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();
|
|
}
|