From e4818e143ad3e37d9e7111eb9c3b7f5032e821fe Mon Sep 17 00:00:00 2001 From: Tim Angus Date: Tue, 13 Aug 2002 19:01:26 +0000 Subject: * Added ownerdrawn FPS, timer, snapshots and lagometer * Fixed bugs in selection after buying/selling upgrades --- src/cgame/cg_draw.c | 1156 ++++++++++++++++++++++++------------------------ src/cgame/cg_event.c | 4 + src/cgame/cg_weapons.c | 14 +- src/game/bg_misc.c | 1 + src/game/bg_public.h | 1 + src/game/g_cmds.c | 25 +- 6 files changed, 613 insertions(+), 588 deletions(-) (limited to 'src') diff --git a/src/cgame/cg_draw.c b/src/cgame/cg_draw.c index 25a62b85..74b5dc61 100644 --- a/src/cgame/cg_draw.c +++ b/src/cgame/cg_draw.c @@ -1030,715 +1030,721 @@ static void CG_DrawTeamSpectators( rectDef_t *rect, float scale, vec4_t color, q cg.spectatorPaintX2 = -1; } } -void CG_OwnerDraw( float x, float y, float w, float h, float text_x, - float text_y, int ownerDraw, int ownerDrawFlags, - int align, float special, float scale, vec4_t color, - qhandle_t shader, int textStyle ) + +/* +================== +CG_DrawFPS +================== +*/ +//TA: personally i think this should be longer - it should really be a cvar +#define FPS_FRAMES 40 +#define FPS_STRING "fps" +static void CG_DrawFPS( rectDef_t *rect, float text_x, float text_y, + float scale, vec4_t color, int align, int textStyle ) { - rectDef_t rect; + char *s; + int tx, w, totalWidth, strLength; + static int previousTimes[ FPS_FRAMES ]; + static int index; + int i, total; + int fps; + static int previous; + int t, frameTime; - if( cg_drawStatus.integer == 0 ) + if( !cg_drawFPS.integer ) return; + + // don't use serverTime, because that will be drifting to + // correct for internet lag changes, timescales, timedemos, etc + t = trap_Milliseconds( ); + frameTime = t - previous; + previous = t; - rect.x = x; - rect.y = y; - rect.w = w; - rect.h = h; - - switch( ownerDraw ) + previousTimes[ index % FPS_FRAMES ] = frameTime; + index++; + + if( index > FPS_FRAMES ) { - case CG_PLAYER_CREDITS_VALUE: - CG_DrawPlayerCreditsValue( &rect, color ); - break; - case CG_PLAYER_BANK_VALUE: - CG_DrawPlayerBankValue( &rect, color ); - break; - case CG_PLAYER_STAMINA: - CG_DrawPlayerStamina( &rect ); - break; - case CG_PLAYER_AMMO_VALUE: - CG_DrawPlayerAmmoValue( &rect, color ); - break; - case CG_PLAYER_CLIPS_VALUE: - CG_DrawPlayerClipsValue( &rect, color ); - break; - case CG_PLAYER_HEALTH: - CG_DrawPlayerHealth( &rect, color ); - break; - case CG_AREA_SYSTEMCHAT: - CG_DrawAreaSystemChat( &rect, scale, color, shader ); - break; - case CG_AREA_TEAMCHAT: - CG_DrawAreaTeamChat( &rect, scale, color, shader ); - break; - case CG_AREA_CHAT: - CG_DrawAreaChat( &rect, scale, color, shader ); - break; - case CG_KILLER: - CG_DrawKiller( &rect, scale, color, shader, textStyle ); - break; - case CG_PLAYER_SELECT: - CG_DrawWeaponSelect( &rect ); - break; - case CG_PLAYER_SELECTTEXT: - CG_DrawWeaponSelectText( &rect, scale, textStyle ); - break; - case CG_SPECTATORS: - CG_DrawTeamSpectators( &rect, scale, color, shader ); - break; + // average multiple frames together to smooth changes out a bit + total = 0; + + for( i = 0 ; i < FPS_FRAMES ; i++ ) + total += previousTimes[ i ]; + + if( !total ) + total = 1; + + fps = 1000 * FPS_FRAMES / total; + + s = va( "%d", fps ); + w = CG_Text_Width( "0", scale, 0 ); + strLength = CG_DrawStrlen( s ); + totalWidth = CG_Text_Width( FPS_STRING, scale, 0 ) + w * strLength; + + switch( align ) + { + case ITEM_ALIGN_LEFT: + tx = rect->x; + break; + + case ITEM_ALIGN_RIGHT: + tx = rect->x + rect->w - totalWidth; + break; + + case ITEM_ALIGN_CENTER: + tx = rect->x + ( rect->w / 2.0f ) - ( totalWidth / 2.0f ); + break; + + default: + tx = 0.0f; + } + + for( i = 0; i < strLength; i++ ) + { + char c[ 2 ]; + + c[ 0 ] = s[ i ]; + c[ 1 ] = '\0'; - //loading screen - case CG_LOAD_LEVELSHOT: - CG_DrawLevelShot( &rect ); - break; - case CG_LOAD_MEDIA: - CG_DrawMediaProgress( &rect, color, scale, align, textStyle ); - break; - case CG_LOAD_MEDIA_LABEL: - CG_DrawMediaProgressLabel( &rect, text_x, text_y, color, scale, align ); - break; - case CG_LOAD_BUILDABLES: - CG_DrawBuildablesProgress( &rect, color, scale, align, textStyle ); - break; - case CG_LOAD_BUILDABLES_LABEL: - CG_DrawBuildablesProgressLabel( &rect, text_x, text_y, color, scale, align ); - break; - case CG_LOAD_CHARMODEL: - CG_DrawCharModelProgress( &rect, color, scale, align, textStyle ); - break; - case CG_LOAD_CHARMODEL_LABEL: - CG_DrawCharModelProgressLabel( &rect, text_x, text_y, color, scale, align ); - break; - case CG_LOAD_OVERALL: - CG_DrawOverallProgress( &rect, color, scale, align, textStyle ); - break; - case CG_LOAD_LEVELNAME: - CG_DrawLevelName( &rect, text_x, text_y, color, scale, align, textStyle ); - break; - case CG_LOAD_MOTD: - CG_DrawMOTD( &rect, text_x, text_y, color, scale, align, textStyle ); - break; - case CG_LOAD_HOSTNAME: - CG_DrawHostname( &rect, text_x, text_y, color, scale, align, textStyle ); - break; - default: - break; + CG_Text_Paint( text_x + tx + i * w, rect->y + text_y, scale, color, c, 0, 0, textStyle ); + } + + CG_Text_Paint( text_x + tx + i * w, rect->y + text_y, scale, color, FPS_STRING, 0, 0, textStyle ); } } -void CG_MouseEvent( int x, int y ) + +/* +================= +CG_DrawTimer +================= +*/ +static void CG_DrawTimer( rectDef_t *rect, float text_x, float text_y, + float scale, vec4_t color, int align, int textStyle ) { - int n; + char *s; + int i, tx, w, totalWidth, strLength; + int mins, seconds, tens; + int msec; - if( ( cg.predictedPlayerState.pm_type == PM_NORMAL || - cg.predictedPlayerState.pm_type == PM_SPECTATOR ) && - cg.showScores == qfalse ) - { - trap_Key_SetCatcher( 0 ); + if( !cg_drawTimer.integer ) return; - } - cgs.cursorX += x; - if( cgs.cursorX < 0 ) - cgs.cursorX = 0; - else if( cgs.cursorX > 640 ) - cgs.cursorX = 640; + msec = cg.time - cgs.levelStartTime; - cgs.cursorY += y; - if( cgs.cursorY < 0 ) - cgs.cursorY = 0; - else if( cgs.cursorY > 480 ) - cgs.cursorY = 480; + seconds = msec / 1000; + mins = seconds / 60; + seconds -= mins * 60; + tens = seconds / 10; + seconds -= tens * 10; - n = Display_CursorType( cgs.cursorX, cgs.cursorY ); - cgs.activeCursor = 0; - if( n == CURSOR_ARROW ) - cgs.activeCursor = cgs.media.selectCursor; - else if( n == CURSOR_SIZER ) - cgs.activeCursor = cgs.media.sizeCursor; + s = va( "%d:%d%d", mins, tens, seconds ); + w = CG_Text_Width( "0", scale, 0 ); + strLength = CG_DrawStrlen( s ); + totalWidth = w * strLength; + + switch( align ) + { + case ITEM_ALIGN_LEFT: + tx = rect->x; + break; - if( cgs.capturedItem ) - Display_MouseMove( cgs.capturedItem, x, y ); - else - Display_MouseMove( NULL, cgs.cursorX, cgs.cursorY ); -} + case ITEM_ALIGN_RIGHT: + tx = rect->x + rect->w - totalWidth; + break; -/* -================== -CG_HideTeamMenus -================== + case ITEM_ALIGN_CENTER: + tx = rect->x + ( rect->w / 2.0f ) - ( totalWidth / 2.0f ); + break; -*/ -void CG_HideTeamMenu( ) -{ - Menus_CloseByName( "teamMenu" ); - Menus_CloseByName( "getMenu" ); -} + default: + tx = 0.0f; + } -/* -================== -CG_ShowTeamMenus -================== + for( i = 0; i < strLength; i++ ) + { + char c[ 2 ]; -*/ -void CG_ShowTeamMenu( ) -{ - Menus_OpenByName("teamMenu"); + c[ 0 ] = s[ i ]; + c[ 1 ] = '\0'; + + CG_Text_Paint( text_x + tx + i * w, rect->y + text_y, scale, color, c, 0, 0, textStyle ); + } } /* ================== -CG_EventHandling +CG_DrawSnapshot ================== - type 0 - no event handling - 1 - team menu - 2 - hud editor - */ -void CG_EventHandling( int type ) +static void CG_DrawSnapshot( rectDef_t *rect, float text_x, float text_y, + float scale, vec4_t color, int align, int textStyle ) { - cgs.eventHandling = type; + char *s; + int w, tx; + + if( !cg_drawSnapshot.integer ) + return; - if( type == CGAME_EVENT_NONE ) - { - CG_HideTeamMenu( ); - } - else if( type == CGAME_EVENT_TEAMMENU ) - { - //CG_ShowTeamMenu(); - } - else if( type == CGAME_EVENT_SCOREBOARD ) + s = va( "time:%d snap:%d cmd:%d", cg.snap->serverTime, + cg.latestSnapshotNum, cgs.serverCommandSequence ); + w = CG_Text_Width( s, scale, 0 ); + + switch( align ) { - - } -} + case ITEM_ALIGN_LEFT: + tx = rect->x; + break; + case ITEM_ALIGN_RIGHT: + tx = rect->x + rect->w - w; + break; + case ITEM_ALIGN_CENTER: + tx = rect->x + ( rect->w / 2.0f ) - ( w / 2.0f ); + break; -void CG_KeyEvent( int key, qboolean down ) -{ - if( !down) - return; - - if( cg.predictedPlayerState.pm_type == PM_NORMAL || - ( cg.predictedPlayerState.pm_type == PM_SPECTATOR && - cg.showScores == qfalse ) ) - { - CG_EventHandling( CGAME_EVENT_NONE ); - trap_Key_SetCatcher( 0 ); - return; + default: + tx = 0.0f; } - Display_HandleKey( key, down, cgs.cursorX, cgs.cursorY ); - - if( cgs.capturedItem ) - { - cgs.capturedItem = NULL; - } - else - { - if( key == K_MOUSE2 && down ) - cgs.capturedItem = Display_CaptureItem( cgs.cursorX, cgs.cursorY ); - } + CG_Text_Paint( text_x + tx, rect->y + text_y, scale, color, s, 0, 0, textStyle ); } -int CG_ClientNumFromName( const char *p ) -{ - int i; - - for( i = 0; i < cgs.maxclients; i++ ) - { - if( cgs.clientinfo[ i ].infoValid && - Q_stricmp( cgs.clientinfo[ i ].name, p ) == 0 ) - return i; - } - - return -1; -} +/* +=============================================================================== -void CG_ShowResponseHead( ) -{ - Menus_OpenByName( "voiceMenu" ); - trap_Cvar_Set( "cl_conXOffset", "72" ); - cg.voiceTime = cg.time; -} +LAGOMETER -void CG_RunMenuScript( char **args ) -{ -} +=============================================================================== +*/ +#define LAG_SAMPLES 128 -void CG_GetTeamColor(vec4_t *color) +typedef struct { - (*color)[0] = (*color)[2] = 0.0f; - (*color)[1] = 0.17f; - (*color)[3] = 0.25f; -} -//END TA UI + int frameSamples[ LAG_SAMPLES ]; + int frameCount; + int snapshotFlags[ LAG_SAMPLES ]; + int snapshotSamples[ LAG_SAMPLES ]; + int snapshotCount; +} lagometer_t; +lagometer_t lagometer; /* -================ -CG_DrawLighting +============== +CG_AddLagometerFrameInfo -================ +Adds the current interpolate / extrapolate bar for this frame +============== */ -static void CG_DrawLighting( void ) +void CG_AddLagometerFrameInfo( void ) { - centity_t *cent; - - cent = &cg_entities[cg.snap->ps.clientNum]; - - if( cg.snap->ps.stats[ STAT_PCLASS ] == PCL_H_BASE ) - { - if( BG_activated( UP_NVG, cg.snap->ps.stats ) ) - CG_DrawPic( 0, 0, 640, 480, cgs.media.humanNV ); - } + int offset; - //fade to black if stamina is low - if( ( cg.snap->ps.stats[ STAT_STAMINA ] < -800 ) && - ( cg.snap->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) ) - { - vec4_t black = { 0, 0, 0, 0 }; - black[ 3 ] = 1.0 - ( (float)( cg.snap->ps.stats[ STAT_STAMINA ] + 1000 ) / 200.0f ); - trap_R_SetColor( black ); - CG_DrawPic( 0, 0, 640, 480, cgs.media.whiteShader ); - trap_R_SetColor( NULL ); - } + offset = cg.time - cg.latestSnapshotTime; + lagometer.frameSamples[ lagometer.frameCount & ( LAG_SAMPLES - 1 ) ] = offset; + lagometer.frameCount++; } /* -=========================================================================================== - - UPPER RIGHT CORNER - -=========================================================================================== -*/ - -/* -================== -CG_DrawSnapshot -================== -*/ -static float CG_DrawSnapshot( float y ) -{ - char *s; - int w; - - s = va( "time:%d snap:%d cmd:%d", cg.snap->serverTime, - cg.latestSnapshotNum, cgs.serverCommandSequence ); - w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; - - CG_DrawBigString( 635 - w, y + 2, s, 1.0F); +============== +CG_AddLagometerSnapshotInfo - return y + BIGCHAR_HEIGHT + 4; -} +Each time a snapshot is received, log its ping time and +the number of snapshots that were dropped before it. -/* -================== -CG_DrawFPS -================== +Pass NULL for a dropped packet. +============== */ -//TA: personally i think this should be longer - it should really be a cvar -#define FPS_FRAMES 40 -static float CG_DrawFPS( float y ) +void CG_AddLagometerSnapshotInfo( snapshot_t *snap ) { - char *s; - int w; - static int previousTimes[ FPS_FRAMES ]; - static int index; - int i, total; - int fps; - static int previous; - int t, frameTime; - - // don't use serverTime, because that will be drifting to - // correct for internet lag changes, timescales, timedemos, etc - t = trap_Milliseconds( ); - frameTime = t - previous; - previous = t; - - previousTimes[ index % FPS_FRAMES ] = frameTime; - index++; - - if( index > FPS_FRAMES ) + // dropped packet + if( !snap ) { - // average multiple frames together to smooth changes out a bit - total = 0; - - for( i = 0 ; i < FPS_FRAMES ; i++ ) - total += previousTimes[ i ]; - - if( !total ) - total = 1; - - fps = 1000 * FPS_FRAMES / total; - - s = va( "%dfps", fps ); - w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; - - CG_DrawBigString( 635 - w, y + 2, s, 1.0F ); + lagometer.snapshotSamples[ lagometer.snapshotCount & ( LAG_SAMPLES - 1 ) ] = -1; + lagometer.snapshotCount++; + return; } - return y + BIGCHAR_HEIGHT + 4; + // add this snapshot's info + lagometer.snapshotSamples[ lagometer.snapshotCount & ( LAG_SAMPLES - 1 ) ] = snap->ping; + lagometer.snapshotFlags[ lagometer.snapshotCount & ( LAG_SAMPLES - 1 ) ] = snap->snapFlags; + lagometer.snapshotCount++; } /* -================= -CG_DrawTimer -================= +============== +CG_DrawDisconnect + +Should we draw something differnet for long lag vs no packets? +============== */ -static float CG_DrawTimer( float y ) +static void CG_DrawDisconnect( void ) { - char *s; - int w; - int mins, seconds, tens; - int msec; + float x, y; + int cmdNum; + usercmd_t cmd; + const char *s; + int w; + vec4_t color = { 1.0f, 1.0f, 1.0f, 1.0f }; - msec = cg.time - cgs.levelStartTime; + // draw the phone jack if we are completely past our buffers + cmdNum = trap_GetCurrentCmdNumber( ) - CMD_BACKUP + 1; + trap_GetUserCmd( cmdNum, &cmd ); + + // special check for map_restart + if( cmd.serverTime <= cg.snap->ps.commandTime || cmd.serverTime > cg.time ) + return; - seconds = msec / 1000; - mins = seconds / 60; - seconds -= mins * 60; - tens = seconds / 10; - seconds -= tens * 10; + // also add text in center of screen + s = "Connection Interrupted"; + w = CG_Text_Width( s, 0.7f, 0 ); + CG_Text_Paint( 320 - w / 2, 100, 0.7f, color, s, 0, 0, ITEM_TEXTSTYLE_SHADOWED ); - s = va( "%d:%d%d", mins, tens, seconds ); - w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; + // blink the icon + if( ( cg.time >> 9 ) & 1 ) + return; - CG_DrawBigString( 635 - w, y + 2, s, 1.0F); + x = 640 - 48; + y = 480 - 48; - return y + BIGCHAR_HEIGHT + 4; + CG_DrawPic( x, y, 48, 48, trap_R_RegisterShader( "gfx/2d/net.tga" ) ); } +#define MAX_LAGOMETER_PING 900 +#define MAX_LAGOMETER_RANGE 300 /* -===================== -CG_DrawUpperRight - -===================== +============== +CG_DrawLagometer +============== */ -static void CG_DrawUpperRight( void ) +static void CG_DrawLagometer( rectDef_t *rect, qhandle_t shader ) { - float y; - - y = 0; - - if( cg_drawSnapshot.integer ) - y = CG_DrawSnapshot( y ); - - if( cg_drawFPS.integer ) - y = CG_DrawFPS( y ); - - if( cg_drawTimer.integer ) - y = CG_DrawTimer( y ); -} - -/* -=========================================================================================== - - LOWER RIGHT CORNER - -=========================================================================================== -*/ + int a, x, y, i; + float v; + float ax, ay, aw, ah, mid, range; + int color; + float vscale; + if( !cg_lagometer.integer ) + { + CG_DrawDisconnect( ); + return; + } -/* -================= -CG_DrawBuildPoints + // + // draw the graph + // + ax = x = rect->x; + ay = y = rect->y; + aw = rect->w; + ah = rect->h; -Draw the small two score display -================= -*/ -/*static float CG_DrawBuildPoints( float y ) -{ - const char *s; - int points, totalpoints, buildpoints; - int team; - int x, w; - float y1; - qboolean spectator; + trap_R_SetColor( NULL ); + CG_DrawPic( x, y, rect->w, rect->h, shader ); - y -= BIGCHAR_HEIGHT + 8; + CG_AdjustFrom640( &ax, &ay, &aw, &ah ); - y1 = y; - + color = -1; + range = ah / 3; + mid = ay + range; - x = 640; - points = cg.snap->ps.persistant[PERS_POINTS]; - totalpoints = cg.snap->ps.persistant[PERS_TOTALPOINTS]; + vscale = range / MAX_LAGOMETER_RANGE; - team = cg.snap->ps.stats[ STAT_PTEAM ]; - - if( team == PTE_ALIENS ) - buildpoints = cgs.alienBuildPoints; - else if( team == PTE_HUMANS ) - buildpoints = cgs.humanBuildPoints; + // draw the frame interpoalte / extrapolate graph + for( a = 0 ; a < aw ; a++ ) + { + i = ( lagometer.frameCount - 1 - a ) & ( LAG_SAMPLES - 1 ); + v = lagometer.frameSamples[ i ]; + v *= vscale; + + if( v > 0 ) + { + if( color != 1 ) + { + color = 1; + trap_R_SetColor( g_color_table[ ColorIndex( COLOR_YELLOW ) ] ); + } + + if( v > range ) + v = range; + + trap_R_DrawStretchPic( ax + aw - a, mid - v, 1, v, 0, 0, 0, 0, cgs.media.whiteShader ); + } + else if( v < 0 ) + { + if( color != 2 ) + { + color = 2; + trap_R_SetColor( g_color_table[ ColorIndex( COLOR_BLUE ) ] ); + } + + v = -v; + if( v > range ) + v = range; + + trap_R_DrawStretchPic( ax + aw - a, mid, 1, v, 0, 0, 0, 0, cgs.media.whiteShader ); + } + } - spectator = ( team == PTE_NONE ); + // draw the snapshot latency / drop graph + range = ah / 2; + vscale = range / MAX_LAGOMETER_PING; - if( !spectator ) + for( a = 0 ; a < aw ; a++ ) { - s = va( "%2i", points ); - w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH + 8; - x -= w; + i = ( lagometer.snapshotCount - 1 - a ) & ( LAG_SAMPLES - 1 ); + v = lagometer.snapshotSamples[ i ]; + + if( v > 0 ) + { + if( lagometer.snapshotFlags[ i ] & SNAPFLAG_RATE_DELAYED ) + { + if( color != 5 ) + { + color = 5; // YELLOW for rate delay + trap_R_SetColor( g_color_table[ ColorIndex( COLOR_YELLOW ) ] ); + } + } + else + { + if( color != 3 ) + { + color = 3; + + trap_R_SetColor( g_color_table[ ColorIndex( COLOR_GREEN ) ] ); + } + } + + v = v * vscale; + + if( v > range ) + v = range; + + trap_R_DrawStretchPic( ax + aw - a, ay + ah - v, 1, v, 0, 0, 0, 0, cgs.media.whiteShader ); + } + else if( v < 0 ) + { + if( color != 4 ) + { + color = 4; // RED for dropped snapshots + trap_R_SetColor( g_color_table[ ColorIndex( COLOR_RED ) ] ); + } + + trap_R_DrawStretchPic( ax + aw - a, ay + ah - range, 1, range, 0, 0, 0, 0, cgs.media.whiteShader ); + } + } - CG_DrawBigString( x + 2, y, s, 1.0F ); + trap_R_SetColor( NULL ); - s = va( "%2i", totalpoints ); - w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH + 8; - x -= w; + if( cg_nopredict.integer || cg_synchronousClients.integer ) + CG_DrawBigString( ax, ay, "snc", 1.0 ); - CG_DrawBigString( x + 2, y, s, 1.0F ); + CG_DrawDisconnect(); +} - s = va( "%2i", buildpoints ); - w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH + 8; - x -= w; - CG_DrawBigString( x + 2, y, s, 1.0F ); - } +void CG_OwnerDraw( float x, float y, float w, float h, float text_x, + float text_y, int ownerDraw, int ownerDrawFlags, + int align, float special, float scale, vec4_t color, + qhandle_t shader, int textStyle ) +{ + rectDef_t rect; - return y1 - 8; -}*/ + if( cg_drawStatus.integer == 0 ) + return; -//=========================================================================================== + rect.x = x; + rect.y = y; + rect.w = w; + rect.h = h; + switch( ownerDraw ) + { + case CG_PLAYER_CREDITS_VALUE: + CG_DrawPlayerCreditsValue( &rect, color ); + break; + case CG_PLAYER_BANK_VALUE: + CG_DrawPlayerBankValue( &rect, color ); + break; + case CG_PLAYER_STAMINA: + CG_DrawPlayerStamina( &rect ); + break; + case CG_PLAYER_AMMO_VALUE: + CG_DrawPlayerAmmoValue( &rect, color ); + break; + case CG_PLAYER_CLIPS_VALUE: + CG_DrawPlayerClipsValue( &rect, color ); + break; + case CG_PLAYER_HEALTH: + CG_DrawPlayerHealth( &rect, color ); + break; + case CG_AREA_SYSTEMCHAT: + CG_DrawAreaSystemChat( &rect, scale, color, shader ); + break; + case CG_AREA_TEAMCHAT: + CG_DrawAreaTeamChat( &rect, scale, color, shader ); + break; + case CG_AREA_CHAT: + CG_DrawAreaChat( &rect, scale, color, shader ); + break; + case CG_KILLER: + CG_DrawKiller( &rect, scale, color, shader, textStyle ); + break; + case CG_PLAYER_SELECT: + CG_DrawWeaponSelect( &rect ); + break; + case CG_PLAYER_SELECTTEXT: + CG_DrawWeaponSelectText( &rect, scale, textStyle ); + break; + case CG_SPECTATORS: + CG_DrawTeamSpectators( &rect, scale, color, shader ); + break; + + //loading screen + case CG_LOAD_LEVELSHOT: + CG_DrawLevelShot( &rect ); + break; + case CG_LOAD_MEDIA: + CG_DrawMediaProgress( &rect, color, scale, align, textStyle ); + break; + case CG_LOAD_MEDIA_LABEL: + CG_DrawMediaProgressLabel( &rect, text_x, text_y, color, scale, align ); + break; + case CG_LOAD_BUILDABLES: + CG_DrawBuildablesProgress( &rect, color, scale, align, textStyle ); + break; + case CG_LOAD_BUILDABLES_LABEL: + CG_DrawBuildablesProgressLabel( &rect, text_x, text_y, color, scale, align ); + break; + case CG_LOAD_CHARMODEL: + CG_DrawCharModelProgress( &rect, color, scale, align, textStyle ); + break; + case CG_LOAD_CHARMODEL_LABEL: + CG_DrawCharModelProgressLabel( &rect, text_x, text_y, color, scale, align ); + break; + case CG_LOAD_OVERALL: + CG_DrawOverallProgress( &rect, color, scale, align, textStyle ); + break; + case CG_LOAD_LEVELNAME: + CG_DrawLevelName( &rect, text_x, text_y, color, scale, align, textStyle ); + break; + case CG_LOAD_MOTD: + CG_DrawMOTD( &rect, text_x, text_y, color, scale, align, textStyle ); + break; + case CG_LOAD_HOSTNAME: + CG_DrawHostname( &rect, text_x, text_y, color, scale, align, textStyle ); + break; + + case CG_FPS: + CG_DrawFPS( &rect, text_x, text_y, scale, color, align, textStyle ); + break; + case CG_TIMER: + CG_DrawTimer( &rect, text_x, text_y, scale, color, align, textStyle ); + break; + case CG_SNAPSHOT: + CG_DrawSnapshot( &rect, text_x, text_y, scale, color, align, textStyle ); + break; + case CG_LAGOMETER: + CG_DrawLagometer( &rect, shader ); + break; + + default: + break; + } +} -/* -=============================================================================== +void CG_MouseEvent( int x, int y ) +{ + int n; -LAGOMETER + if( ( cg.predictedPlayerState.pm_type == PM_NORMAL || + cg.predictedPlayerState.pm_type == PM_SPECTATOR ) && + cg.showScores == qfalse ) + { + trap_Key_SetCatcher( 0 ); + return; + } -=============================================================================== -*/ + cgs.cursorX += x; + if( cgs.cursorX < 0 ) + cgs.cursorX = 0; + else if( cgs.cursorX > 640 ) + cgs.cursorX = 640; -#define LAG_SAMPLES 128 + cgs.cursorY += y; + if( cgs.cursorY < 0 ) + cgs.cursorY = 0; + else if( cgs.cursorY > 480 ) + cgs.cursorY = 480; -typedef struct -{ - int frameSamples[ LAG_SAMPLES ]; - int frameCount; - int snapshotFlags[ LAG_SAMPLES ]; - int snapshotSamples[ LAG_SAMPLES ]; - int snapshotCount; -} lagometer_t; + n = Display_CursorType( cgs.cursorX, cgs.cursorY ); + cgs.activeCursor = 0; + if( n == CURSOR_ARROW ) + cgs.activeCursor = cgs.media.selectCursor; + else if( n == CURSOR_SIZER ) + cgs.activeCursor = cgs.media.sizeCursor; -lagometer_t lagometer; + if( cgs.capturedItem ) + Display_MouseMove( cgs.capturedItem, x, y ); + else + Display_MouseMove( NULL, cgs.cursorX, cgs.cursorY ); +} /* -============== -CG_AddLagometerFrameInfo +================== +CG_HideTeamMenus +================== -Adds the current interpolate / extrapolate bar for this frame -============== */ -void CG_AddLagometerFrameInfo( void ) +void CG_HideTeamMenu( ) { - int offset; + Menus_CloseByName( "teamMenu" ); + Menus_CloseByName( "getMenu" ); +} - offset = cg.time - cg.latestSnapshotTime; - lagometer.frameSamples[ lagometer.frameCount & ( LAG_SAMPLES - 1 ) ] = offset; - lagometer.frameCount++; +/* +================== +CG_ShowTeamMenus +================== + +*/ +void CG_ShowTeamMenu( ) +{ + Menus_OpenByName("teamMenu"); } /* -============== -CG_AddLagometerSnapshotInfo - -Each time a snapshot is received, log its ping time and -the number of snapshots that were dropped before it. +================== +CG_EventHandling +================== + type 0 - no event handling + 1 - team menu + 2 - hud editor -Pass NULL for a dropped packet. -============== */ -void CG_AddLagometerSnapshotInfo( snapshot_t *snap ) +void CG_EventHandling( int type ) { - // dropped packet - if( !snap ) + cgs.eventHandling = type; + + if( type == CGAME_EVENT_NONE ) { - lagometer.snapshotSamples[ lagometer.snapshotCount & ( LAG_SAMPLES - 1 ) ] = -1; - lagometer.snapshotCount++; - return; + CG_HideTeamMenu( ); + } + else if( type == CGAME_EVENT_TEAMMENU ) + { + //CG_ShowTeamMenu(); + } + else if( type == CGAME_EVENT_SCOREBOARD ) + { + } - - // add this snapshot's info - lagometer.snapshotSamples[ lagometer.snapshotCount & ( LAG_SAMPLES - 1 ) ] = snap->ping; - lagometer.snapshotFlags[ lagometer.snapshotCount & ( LAG_SAMPLES - 1 ) ] = snap->snapFlags; - lagometer.snapshotCount++; } -/* -============== -CG_DrawDisconnect -Should we draw something differnet for long lag vs no packets? -============== -*/ -static void CG_DrawDisconnect( void ) -{ - float x, y; - int cmdNum; - usercmd_t cmd; - const char *s; - int w; - // draw the phone jack if we are completely past our buffers - cmdNum = trap_GetCurrentCmdNumber( ) - CMD_BACKUP + 1; - trap_GetUserCmd( cmdNum, &cmd ); - - // special check for map_restart - if( cmd.serverTime <= cg.snap->ps.commandTime || cmd.serverTime > cg.time ) +void CG_KeyEvent( int key, qboolean down ) +{ + if( !down) return; - // also add text in center of screen - s = "Connection Interrupted"; - w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; - CG_DrawBigString( 320 - w / 2, 100, s, 1.0F); - - // blink the icon - if( ( cg.time >> 9 ) & 1 ) + if( cg.predictedPlayerState.pm_type == PM_NORMAL || + ( cg.predictedPlayerState.pm_type == PM_SPECTATOR && + cg.showScores == qfalse ) ) + { + CG_EventHandling( CGAME_EVENT_NONE ); + trap_Key_SetCatcher( 0 ); return; + } - x = 640 - 48; - y = 480 - 48; + Display_HandleKey( key, down, cgs.cursorX, cgs.cursorY ); - CG_DrawPic( x, y, 48, 48, trap_R_RegisterShader( "gfx/2d/net.tga" ) ); + if( cgs.capturedItem ) + { + cgs.capturedItem = NULL; + } + else + { + if( key == K_MOUSE2 && down ) + cgs.capturedItem = Display_CaptureItem( cgs.cursorX, cgs.cursorY ); + } } -#define MAX_LAGOMETER_PING 900 -#define MAX_LAGOMETER_RANGE 300 - -/* -============== -CG_DrawLagometer -============== -*/ -static void CG_DrawLagometer( void ) +int CG_ClientNumFromName( const char *p ) { - int a, x, y, i; - float v; - float ax, ay, aw, ah, mid, range; - int color; - float vscale; - - if( !cg_lagometer.integer || cgs.localServer ) + int i; + + for( i = 0; i < cgs.maxclients; i++ ) { - CG_DrawDisconnect( ); - return; + if( cgs.clientinfo[ i ].infoValid && + Q_stricmp( cgs.clientinfo[ i ].name, p ) == 0 ) + return i; } + + return -1; +} - // - // draw the graph - // - x = 640 - 48; - y = 480 - 144; +void CG_ShowResponseHead( ) +{ + Menus_OpenByName( "voiceMenu" ); + trap_Cvar_Set( "cl_conXOffset", "72" ); + cg.voiceTime = cg.time; +} - trap_R_SetColor( NULL ); - CG_DrawPic( x, y, 48, 48, cgs.media.lagometerShader ); +void CG_RunMenuScript( char **args ) +{ +} - ax = x; - ay = y; - aw = 48; - ah = 48; - CG_AdjustFrom640( &ax, &ay, &aw, &ah ); - color = -1; - range = ah / 3; - mid = ay + range; +void CG_GetTeamColor(vec4_t *color) +{ + (*color)[0] = (*color)[2] = 0.0f; + (*color)[1] = 0.17f; + (*color)[3] = 0.25f; +} +//END TA UI - vscale = range / MAX_LAGOMETER_RANGE; - // draw the frame interpoalte / extrapolate graph - for( a = 0 ; a < aw ; a++ ) +/* +================ +CG_DrawLighting + +================ +*/ +static void CG_DrawLighting( void ) +{ + centity_t *cent; + + cent = &cg_entities[cg.snap->ps.clientNum]; + + if( cg.snap->ps.stats[ STAT_PCLASS ] == PCL_H_BASE ) { - i = ( lagometer.frameCount - 1 - a ) & ( LAG_SAMPLES - 1 ); - v = lagometer.frameSamples[ i ]; - v *= vscale; - - if( v > 0 ) - { - if( color != 1 ) - { - color = 1; - trap_R_SetColor( g_color_table[ ColorIndex( COLOR_YELLOW ) ] ); - } - - if( v > range ) - v = range; - - trap_R_DrawStretchPic( ax + aw - a, mid - v, 1, v, 0, 0, 0, 0, cgs.media.whiteShader ); - } - else if( v < 0 ) - { - if( color != 2 ) - { - color = 2; - trap_R_SetColor( g_color_table[ ColorIndex( COLOR_BLUE ) ] ); - } - - v = -v; - if( v > range ) - v = range; - - trap_R_DrawStretchPic( ax + aw - a, mid, 1, v, 0, 0, 0, 0, cgs.media.whiteShader ); - } + if( BG_activated( UP_NVG, cg.snap->ps.stats ) ) + CG_DrawPic( 0, 0, 640, 480, cgs.media.humanNV ); } - // draw the snapshot latency / drop graph - range = ah / 2; - vscale = range / MAX_LAGOMETER_PING; - - for( a = 0 ; a < aw ; a++ ) + //fade to black if stamina is low + if( ( cg.snap->ps.stats[ STAT_STAMINA ] < -800 ) && + ( cg.snap->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) ) { - i = ( lagometer.snapshotCount - 1 - a ) & ( LAG_SAMPLES - 1 ); - v = lagometer.snapshotSamples[ i ]; - - if( v > 0 ) - { - if( lagometer.snapshotFlags[ i ] & SNAPFLAG_RATE_DELAYED ) - { - if( color != 5 ) - { - color = 5; // YELLOW for rate delay - trap_R_SetColor( g_color_table[ ColorIndex( COLOR_YELLOW ) ] ); - } - } - else - { - if( color != 3 ) - { - color = 3; - - trap_R_SetColor( g_color_table[ ColorIndex( COLOR_GREEN ) ] ); - } - } - - v = v * vscale; - - if( v > range ) - v = range; - - trap_R_DrawStretchPic( ax + aw - a, ay + ah - v, 1, v, 0, 0, 0, 0, cgs.media.whiteShader ); - } - else if( v < 0 ) - { - if( color != 4 ) - { - color = 4; // RED for dropped snapshots - trap_R_SetColor( g_color_table[ ColorIndex( COLOR_RED ) ] ); - } - - trap_R_DrawStretchPic( ax + aw - a, ay + ah - range, 1, range, 0, 0, 0, 0, cgs.media.whiteShader ); - } + vec4_t black = { 0, 0, 0, 0 }; + black[ 3 ] = 1.0 - ( (float)( cg.snap->ps.stats[ STAT_STAMINA ] + 1000 ) / 200.0f ); + trap_R_SetColor( black ); + CG_DrawPic( 0, 0, 640, 480, cgs.media.whiteShader ); + trap_R_SetColor( NULL ); } +} - trap_R_SetColor( NULL ); +/* +=========================================================================================== - if( cg_nopredict.integer || cg_synchronousClients.integer ) - CG_DrawBigString( ax, ay, "snc", 1.0 ); + LOWER RIGHT CORNER - CG_DrawDisconnect(); -} +=========================================================================================== +*/ @@ -2366,8 +2372,8 @@ static void CG_Draw2D( void ) BG_FindHudNameForClass( cg.predictedPlayerState.stats[ STAT_PCLASS ] ) ), qtrue ); } - CG_DrawAmmoWarning(); - CG_DrawCrosshair(); + CG_DrawAmmoWarning( ); + CG_DrawCrosshair( ); if( BG_gotItem( UP_HELMET, cg.snap->ps.stats ) ) CG_Scanner( ); @@ -2377,12 +2383,8 @@ static void CG_Draw2D( void ) } } - CG_DrawVote(); - CG_DrawTeamVote(); - - CG_DrawLagometer(); - - CG_DrawUpperRight(); + CG_DrawVote( ); + CG_DrawTeamVote( ); if( !CG_DrawFollow( ) ) CG_DrawWarmup(); diff --git a/src/cgame/cg_event.c b/src/cgame/cg_event.c index 3cab52cd..4ae78987 100644 --- a/src/cgame/cg_event.c +++ b/src/cgame/cg_event.c @@ -806,6 +806,10 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) DEBUGNAME("EV_CHANGE_WEAPON"); trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.selectSound ); break; + case EV_NEXT_WEAPON: + DEBUGNAME("EV_NEXT_WEAPON"); + CG_NextWeapon_f( ); + break; case EV_FIRE_WEAPON: DEBUGNAME("EV_FIRE_WEAPON"); CG_FireWeapon( cent ); diff --git a/src/cgame/cg_weapons.c b/src/cgame/cg_weapons.c index cc5e745b..d8441016 100644 --- a/src/cgame/cg_weapons.c +++ b/src/cgame/cg_weapons.c @@ -1552,14 +1552,6 @@ void CG_DrawWeaponSelect( rectDef_t *rect ) else x += iconsize; } - - /*//TA: yuck! :) - if( y == 10 ) - { - trap_R_SetColor( NULL ); - return; - }*/ - } @@ -1583,7 +1575,8 @@ void CG_DrawWeaponSelectText( rectDef_t *rect, float scale, int textStyle ) // draw the selected name if( cg.weaponSelect <= 32 ) { - if( cg_weapons[ cg.weaponSelect ].registered ) + if( cg_weapons[ cg.weaponSelect ].registered && + BG_gotWeapon( cg.weaponSelect, cg.snap->ps.stats ) ) { if( name = cg_weapons[ cg.weaponSelect ].humanName ) { @@ -1595,7 +1588,8 @@ void CG_DrawWeaponSelectText( rectDef_t *rect, float scale, int textStyle ) } else if( cg.weaponSelect > 32 ) { - if( cg_upgrades[ cg.weaponSelect - 32 ].registered ) + if( cg_upgrades[ cg.weaponSelect - 32 ].registered && + BG_gotItem( cg.weaponSelect - 32, cg.snap->ps.stats ) ) { if( name = cg_upgrades[ cg.weaponSelect - 32 ].humanName ) { diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c index c6a46353..3f60271b 100644 --- a/src/game/bg_misc.c +++ b/src/game/bg_misc.c @@ -3368,6 +3368,7 @@ char *eventnames[] = { "EV_NOAMMO", "EV_CHANGE_WEAPON", + "EV_NEXT_WEAPON", "EV_FIRE_WEAPON", "EV_FIRE_WEAPON2", "EV_FIRE_WEAPONBOTH", diff --git a/src/game/bg_public.h b/src/game/bg_public.h index 7e8483de..2d59fe82 100644 --- a/src/game/bg_public.h +++ b/src/game/bg_public.h @@ -504,6 +504,7 @@ typedef enum { EV_NOAMMO, EV_CHANGE_WEAPON, + EV_NEXT_WEAPON, EV_FIRE_WEAPON, EV_FIRE_WEAPON2, EV_FIRE_WEAPONBOTH, diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c index 66e0f16a..331326ae 100644 --- a/src/game/g_cmds.c +++ b/src/game/g_cmds.c @@ -1851,9 +1851,21 @@ void Cmd_Buy_f( gentity_t *ent ) int i; gentity_t *mcuEntity; qboolean nearMCU = qfalse; - int weapon, upgrade; + int weapon, upgrade, numItems = 0; int quan, clips, maxClips; + for( i = UP_NONE; i < UP_NUM_UPGRADES; i++ ) + { + if( BG_gotItem( i, ent->client->ps.stats ) ) + numItems++; + } + + for( i = WP_NONE; i < WP_NUM_WEAPONS; i++ ) + { + if( BG_gotWeapon( i, ent->client->ps.stats ) ) + numItems++; + } + trap_Argv( 1, s, sizeof( s ) ); //aliens don't buy stuff @@ -2029,6 +2041,9 @@ void Cmd_Buy_f( gentity_t *ent ) trap_SendServerCommand( ent-g_entities, va("print \"Unknown item\n\"" ) ); } + //if the buyer previously had no items at all, force a new selection + if( numItems == 0 ) + G_AddEvent( ent, EV_NEXT_WEAPON, 0 ); } @@ -2086,6 +2101,10 @@ void Cmd_Sell_f( gentity_t *ent ) //add to funds ent->client->ps.persistant[ PERS_CREDIT ] += BG_FindPriceForWeapon( weapon ); } + + //if we have this weapon selected, force a new selection + if( weapon == ent->client->ps.weapon ) + G_AddEvent( ent, EV_NEXT_WEAPON, 0 ); } else if( upgrade != UP_NONE ) { @@ -2097,6 +2116,10 @@ void Cmd_Sell_f( gentity_t *ent ) //add to funds ent->client->ps.persistant[ PERS_CREDIT ] += BG_FindPriceForUpgrade( upgrade ); } + + //if we have this upgrade selected, force a new selection + if( upgrade == ent->client->pers.cmd.weapon - 32 ) + G_AddEvent( ent, EV_NEXT_WEAPON, 0 ); } else { -- cgit