Portable Half-Life SDK. GoldSource and Xash3D. Crossplatform.
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.

327 lines
8.0 KiB

9 years ago
/***
*
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
//
// saytext.cpp
//
// implementation of CHudSayText class
//
#include "hud.h"
#include "cl_util.h"
#include "parsemsg.h"
#include <string.h>
#include <stdio.h>
#if USE_VGUI
#include "vgui_TeamFortressViewport.h"
#endif
9 years ago
extern float *GetClientColor( int clientIndex );
#define MAX_LINES 5
#define MAX_CHARS_PER_LINE 256 /* it can be less than this, depending on char size */
// allow 20 pixels on either side of the text
#define MAX_LINE_WIDTH ( ScreenWidth - 40 )
#define LINE_START 10
static float SCROLL_SPEED = 5;
9 years ago
static char g_szLineBuffer[MAX_LINES + 1][MAX_CHARS_PER_LINE];
static float *g_pflNameColors[MAX_LINES + 1];
static int g_iNameLengths[MAX_LINES + 1];
9 years ago
static float flScrollTime = 0; // the time at which the lines next scroll up
static int Y_START = 0;
static int line_height = 0;
DECLARE_MESSAGE( m_SayText, SayText )
9 years ago
9 years ago
int CHudSayText::Init( void )
9 years ago
{
gHUD.AddHudElem( this );
HOOK_MESSAGE( SayText );
InitHUDData();
9 years ago
m_HUD_saytext = gEngfuncs.pfnRegisterVariable( "hud_saytext", "1", 0 );
9 years ago
m_HUD_saytext_time = gEngfuncs.pfnRegisterVariable( "hud_saytext_time", "5", 0 );
m_iFlags |= HUD_INTERMISSION; // is always drawn during an intermission
return 1;
}
9 years ago
void CHudSayText::InitHUDData( void )
9 years ago
{
memset( g_szLineBuffer, 0, sizeof g_szLineBuffer );
memset( g_pflNameColors, 0, sizeof g_pflNameColors );
memset( g_iNameLengths, 0, sizeof g_iNameLengths );
}
9 years ago
int CHudSayText::VidInit( void )
9 years ago
{
return 1;
}
int ScrollTextUp( void )
{
ConsolePrint( g_szLineBuffer[0] ); // move the first line into the console buffer
g_szLineBuffer[MAX_LINES][0] = 0;
memmove( g_szLineBuffer[0], g_szLineBuffer[1], sizeof(g_szLineBuffer) - sizeof(g_szLineBuffer[0]) ); // overwrite the first line
memmove( &g_pflNameColors[0], &g_pflNameColors[1], sizeof(g_pflNameColors) - sizeof(g_pflNameColors[0]) );
memmove( &g_iNameLengths[0], &g_iNameLengths[1], sizeof(g_iNameLengths) - sizeof(g_iNameLengths[0]) );
g_szLineBuffer[MAX_LINES-1][0] = 0;
9 years ago
if( g_szLineBuffer[0][0] == ' ' ) // also scroll up following lines
9 years ago
{
g_szLineBuffer[0][0] = 2;
return 1 + ScrollTextUp();
}
return 1;
}
9 years ago
int CHudSayText::Draw( float flTime )
9 years ago
{
int y = Y_START;
#if USE_VGUI
if( ( gViewPort && gViewPort->AllowedToPrintText() == FALSE ) )
return 1;
#endif
if ( !m_HUD_saytext->value )
return 1;
9 years ago
// make sure the scrolltime is within reasonable bounds, to guard against the clock being reset
flScrollTime = Q_min( flScrollTime, flTime + m_HUD_saytext_time->value );
9 years ago
9 years ago
if( flScrollTime <= flTime )
9 years ago
{
9 years ago
if( *g_szLineBuffer[0] )
9 years ago
{
flScrollTime = flTime + m_HUD_saytext_time->value;
// push the console up
ScrollTextUp();
}
else
9 years ago
{
// buffer is empty, just disable drawing of this section
9 years ago
m_iFlags &= ~HUD_ACTIVE;
}
}
9 years ago
for( int i = 0; i < MAX_LINES; i++ )
9 years ago
{
9 years ago
if( *g_szLineBuffer[i] )
9 years ago
{
9 years ago
if( *g_szLineBuffer[i] == 2 && g_pflNameColors[i] )
9 years ago
{
// it's a saytext string
9 years ago
static char buf[MAX_PLAYER_NAME_LENGTH + 32];
9 years ago
// draw the first x characters in the player color
strncpy( buf, g_szLineBuffer[i], Q_min(g_iNameLengths[i], MAX_PLAYER_NAME_LENGTH + 31 ) );
buf[Q_min( g_iNameLengths[i], MAX_PLAYER_NAME_LENGTH + 31 )] = 0;
9 years ago
DrawSetTextColor( g_pflNameColors[i][0], g_pflNameColors[i][1], g_pflNameColors[i][2] );
int x = DrawConsoleString( LINE_START, y, buf );
// color is reset after each string draw
DrawConsoleString( x, y, g_szLineBuffer[i] + g_iNameLengths[i] );
}
else
{
// normal draw
DrawConsoleString( LINE_START, y, g_szLineBuffer[i] );
}
}
y += line_height;
}
return 1;
}
9 years ago
int CHudSayText::MsgFunc_SayText( const char *pszName, int iSize, void *pbuf )
9 years ago
{
BEGIN_READ( pbuf, iSize );
int client_index = READ_BYTE(); // the client who spoke the message
SayTextPrint( READ_STRING(), iSize - 1, client_index );
9 years ago
9 years ago
return 1;
}
9 years ago
void CHudSayText::SayTextPrint( const char *pszBuf, int iBufSize, int clientIndex )
9 years ago
{
#if USE_VGUI
if( gViewPort && gViewPort->AllowedToPrintText() == FALSE )
{
// Print it straight to the console
ConsolePrint( pszBuf );
return;
}
#endif
9 years ago
int i;
9 years ago
// find an empty string slot
9 years ago
for( i = 0; i < MAX_LINES; i++ )
9 years ago
{
9 years ago
if( !( *g_szLineBuffer[i] ) )
9 years ago
break;
}
9 years ago
if( i == MAX_LINES )
9 years ago
{
// force scroll buffer up
ScrollTextUp();
i = MAX_LINES - 1;
}
g_iNameLengths[i] = 0;
g_pflNameColors[i] = NULL;
// if it's a say message, search for the players name in the string
9 years ago
if( *pszBuf == 2 && clientIndex > 0 )
9 years ago
{
GetPlayerInfo( clientIndex, &g_PlayerInfoList[clientIndex] );
const char *pName = g_PlayerInfoList[clientIndex].name;
9 years ago
if( pName )
9 years ago
{
const char *nameInString = strstr( pszBuf, pName );
9 years ago
if( nameInString )
9 years ago
{
9 years ago
g_iNameLengths[i] = strlen( pName ) + ( nameInString - pszBuf );
9 years ago
g_pflNameColors[i] = GetClientColor( clientIndex );
}
}
}
strncpy( g_szLineBuffer[i], pszBuf, Q_max( iBufSize - 1, MAX_CHARS_PER_LINE - 1 ) );
9 years ago
// make sure the text fits in one line
EnsureTextFitsInOneLineAndWrapIfHaveTo( i );
// Set scroll time
9 years ago
if( i == 0 )
9 years ago
{
flScrollTime = gHUD.m_flTime + m_HUD_saytext_time->value;
}
m_iFlags |= HUD_ACTIVE;
PlaySound( "misc/talk.wav", 1 );
9 years ago
if( ScreenHeight >= 480 )
9 years ago
Y_START = ScreenHeight - 60;
else
Y_START = ScreenHeight - 45;
9 years ago
Y_START -= ( line_height * ( MAX_LINES + 1 ) );
9 years ago
}
9 years ago
void CHudSayText::EnsureTextFitsInOneLineAndWrapIfHaveTo( int line )
9 years ago
{
int line_width = 0;
GetConsoleStringSize( g_szLineBuffer[line], &line_width, &line_height );
9 years ago
if( ( line_width + LINE_START ) > MAX_LINE_WIDTH )
{
// string is too long to fit on line
9 years ago
// scan the string until we find what word is too long, and wrap the end of the sentence after the word
int length = LINE_START;
int tmp_len = 0;
char *last_break = NULL;
9 years ago
for( char *x = g_szLineBuffer[line]; *x != 0; x++ )
9 years ago
{
// check for a color change, if so skip past it
9 years ago
if( x[0] == '/' && x[1] == '(' )
9 years ago
{
x += 2;
// skip forward until past mode specifier
while ( *x != 0 && *x != ')' )
x++;
9 years ago
if( *x != 0 )
9 years ago
x++;
9 years ago
if( *x == 0 )
9 years ago
break;
}
char buf[2];
buf[1] = 0;
9 years ago
if( *x == ' ' && x != g_szLineBuffer[line] ) // store each line break, except for the very first character
9 years ago
last_break = x;
buf[0] = *x; // get the length of the current character
GetConsoleStringSize( buf, &tmp_len, &line_height );
length += tmp_len;
9 years ago
if( length > MAX_LINE_WIDTH )
{
// needs to be broken up
if( !last_break )
last_break = x - 1;
9 years ago
// x = last_break;
9 years ago
// find an empty string slot
int j;
do
{
9 years ago
for( j = 0; j < MAX_LINES; j++ )
9 years ago
{
9 years ago
if( !( *g_szLineBuffer[j] ) )
9 years ago
break;
}
9 years ago
if( j == MAX_LINES )
9 years ago
{
// need to make more room to display text, scroll stuff up then fix the pointers
int linesmoved = ScrollTextUp();
line -= linesmoved;
9 years ago
last_break = last_break - ( sizeof(g_szLineBuffer[0]) * linesmoved );
9 years ago
}
}
9 years ago
while( j == MAX_LINES );
9 years ago
// copy remaining string into next buffer, making sure it starts with a space character
9 years ago
if( (char)*last_break == (char)' ' )
9 years ago
{
9 years ago
int linelen = strlen( g_szLineBuffer[j] );
int remaininglen = strlen( last_break );
9 years ago
9 years ago
if( ( linelen - remaininglen ) <= MAX_CHARS_PER_LINE )
9 years ago
strcat( g_szLineBuffer[j], last_break );
}
else
{
9 years ago
if ( ( strlen( g_szLineBuffer[j] ) - strlen( last_break ) - 2 ) < MAX_CHARS_PER_LINE )
9 years ago
{
strcat( g_szLineBuffer[j], " " );
strcat( g_szLineBuffer[j], last_break );
}
}
*last_break = 0; // cut off the last string
EnsureTextFitsInOneLineAndWrapIfHaveTo( j );
break;
}
}
}
}