2011-02-18 14:31:32 +00:00
|
|
|
/*
|
|
|
|
** Copyright (C) 2004 by the Q3Rally Development team
|
|
|
|
** All rights reserved.
|
|
|
|
**
|
|
|
|
** cg_rally_hud.c
|
|
|
|
**
|
|
|
|
** Components for the common HUD elements.
|
|
|
|
**
|
|
|
|
** Author: STONELANCE
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "cg_local.h"
|
|
|
|
|
|
|
|
float colors[4][4] = {
|
|
|
|
// { 0.2, 1.0, 0.2, 1.0 } , { 1.0, 0.2, 0.2, 1.0 }, {0.5, 0.5, 0.5, 1} };
|
|
|
|
{ 1.0f, 0.69f, 0.0f, 1.0f } , // normal
|
|
|
|
{ 1.0f, 0.2f, 0.2f, 1.0f }, // low health
|
|
|
|
{ 0.5f, 0.5f, 0.5f, 1.0f }, // weapon firing
|
|
|
|
{ 1.0f, 1.0f, 1.0f, 1.0f } // health > 100
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
CG_DrawRearviewMirror
|
|
|
|
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
void CG_DrawRearviewMirror( float x, float y, float w, float h) {
|
|
|
|
//static int lastLowFPSTime;
|
|
|
|
int i;
|
|
|
|
//int fps;
|
|
|
|
float mx, my, mw, mh;
|
2012-10-15 22:46:54 +00:00
|
|
|
int tmp;
|
2011-02-18 14:31:32 +00:00
|
|
|
|
|
|
|
if ( !cg_drawRearView.integer )
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (cg.snap->ps.pm_type == PM_INTERMISSION)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (cgs.clientinfo[cg.snap->ps.clientNum].team == TEAM_SPECTATOR)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
if (cg_fpsLimit.integer >= 100)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (cg_fpsLimit.integer > 0){
|
|
|
|
fps = 0;
|
|
|
|
if (cg.frametime){
|
|
|
|
fps = 1000 / cg.frametime;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lastLowFPSTime + 3000 >= cg.time){
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fps < cg_fpsLimit.integer){
|
|
|
|
lastLowFPSTime = cg.time;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
mx = x - 8;
|
|
|
|
my = y - 7;
|
|
|
|
mw = w * 1.0534F;
|
|
|
|
mh = h * 1.2F;
|
|
|
|
|
|
|
|
CG_AdjustFrom640( &x, &y, &w, &h );
|
|
|
|
|
|
|
|
cg.mirrorRefdef.x = x;
|
|
|
|
cg.mirrorRefdef.y = y;
|
|
|
|
cg.mirrorRefdef.width = w;
|
|
|
|
cg.mirrorRefdef.height = h;
|
|
|
|
|
|
|
|
cg.mirrorRefdef.fov_x = 70;
|
2012-10-15 22:46:54 +00:00
|
|
|
tmp = cg.mirrorRefdef.width / tan( cg.mirrorRefdef.fov_x / 360 * M_PI );
|
|
|
|
cg.mirrorRefdef.fov_y = atan2( cg.mirrorRefdef.height, tmp );
|
|
|
|
cg.mirrorRefdef.fov_y = cg.mirrorRefdef.fov_y * 360 / M_PI;
|
2011-02-18 14:31:32 +00:00
|
|
|
|
|
|
|
cg.mirrorRefdef.time = cg.time;
|
|
|
|
cg.mirrorRefdef.rdflags = 0;
|
|
|
|
|
|
|
|
// AnglesToAxis( cg.predictedPlayerState.viewangles, mirrorRefdef.viewaxis );
|
|
|
|
// VectorInverse( mirrorRefdef.viewaxis[0] );
|
|
|
|
// VectorInverse( mirrorRefdef.viewaxis[1] );
|
|
|
|
|
|
|
|
// VectorCopy( cg.predictedPlayerState.origin, mirrorRefdef.vieworg );
|
|
|
|
// VectorMA( mirrorRefdef.vieworg, 16, mirrorRefdef.viewaxis[2], mirrorRefdef.vieworg );
|
|
|
|
|
|
|
|
// add entities and graphics to rearview scene
|
|
|
|
if (cg_rearViewRenderLevel.integer & RL_MARKS){
|
|
|
|
CG_AddMarks();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cg_rearViewRenderLevel.integer & RL_SMOKE){
|
|
|
|
CG_AddLocalEntities();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cg_rearViewRenderLevel.integer & RL_PLAYERS || cg_rearViewRenderLevel.integer & RL_OBJECTS){
|
|
|
|
for (i = 0; i < cg.snap->numEntities; i++){
|
|
|
|
if (!(cg_rearViewRenderLevel.integer & RL_OBJECTS)){
|
|
|
|
// skip non-players
|
|
|
|
if ( cg.snap->entities[i].eType != ET_PLAYER ) continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(cg_rearViewRenderLevel.integer & RL_PLAYERS)){
|
|
|
|
// skip players
|
|
|
|
if ( cg.snap->entities[i].eType == ET_PLAYER ) continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: dont re-lerp entity
|
|
|
|
CG_AddCEntity( &cg_entities[ cg.snap->entities[ i ].number ] );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
trap_R_RenderScene( &cg.mirrorRefdef );
|
|
|
|
CG_DrawPic( mx, my, mw, mh, cgs.media.rearviewMirrorShader );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
CG_DrawMMap
|
|
|
|
|
|
|
|
TBB - minimap EXPERIMENTAL -
|
|
|
|
modified rearview but only render stuff from +8192(Z) from
|
|
|
|
center of bsp, pitched downward, and render only players (flags for ctf).
|
|
|
|
this will probably drop fps, hopefully not too much and ,
|
|
|
|
might have to make a cvar for displaying it plus opacity
|
|
|
|
trying to get this to work like the minimap from UrT
|
|
|
|
from scratch. must try to make it 2d bitmap
|
|
|
|
================
|
2016-04-14 12:01:56 +00:00
|
|
|
*/
|
2011-02-18 14:31:32 +00:00
|
|
|
|
|
|
|
void CG_DrawMMap( float x, float y, float w, float h ) {
|
|
|
|
int i;
|
|
|
|
float mx, my, mw, mh;
|
2012-10-15 22:46:54 +00:00
|
|
|
int tmp;
|
2011-02-18 14:31:32 +00:00
|
|
|
|
|
|
|
if ( !cg_drawMMap.integer )
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (cg.snap->ps.pm_type == PM_INTERMISSION)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (cgs.clientinfo[cg.snap->ps.clientNum].team == TEAM_SPECTATOR)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* TBB - minimap to show for only racing and team racing no weapons (for now)
|
|
|
|
if ( cgs.gametype != GT_RACING )
|
|
|
|
return;
|
|
|
|
|
|
|
|
if ( (cgs.gametype != GT_RACING) || (cgs.gametype != GT_TEAM_RACING) )
|
2016-04-14 12:01:56 +00:00
|
|
|
return; */
|
2011-02-18 14:31:32 +00:00
|
|
|
|
|
|
|
mx = x ;
|
|
|
|
my = y ;
|
|
|
|
mw = w;
|
|
|
|
mh = h;
|
|
|
|
|
|
|
|
CG_AdjustFrom640( &x, &y, &w, &h );
|
|
|
|
|
|
|
|
cg.mmapRefdef.x = x;
|
|
|
|
cg.mmapRefdef.y = y;
|
|
|
|
cg.mmapRefdef.width = w;
|
|
|
|
cg.mmapRefdef.height = h;
|
|
|
|
|
|
|
|
cg.mmapRefdef.fov_x = 70;
|
2012-10-15 22:46:54 +00:00
|
|
|
tmp = cg.mmapRefdef.width / tan( cg.mmapRefdef.fov_x / 360 * M_PI );
|
|
|
|
cg.mmapRefdef.fov_y = atan2( cg.mmapRefdef.height, tmp );
|
|
|
|
cg.mmapRefdef.fov_y = cg.mmapRefdef.fov_y * 360 / M_PI;
|
2011-02-18 14:31:32 +00:00
|
|
|
|
|
|
|
cg.mmapRefdef.time = cg.time;
|
|
|
|
cg.mmapRefdef.rdflags = 0;
|
|
|
|
|
|
|
|
// AnglesToAxis( cg.predictedPlayerState.viewangles, mirrorRefdef.viewaxis );
|
|
|
|
// VectorInverse( mirrorRefdef.viewaxis[0] );
|
|
|
|
// VectorInverse( mirrorRefdef.viewaxis[1] );
|
|
|
|
|
|
|
|
// VectorCopy( cg.predictedPlayerState.origin, mirrorRefdef.vieworg );
|
|
|
|
// VectorMA( mirrorRefdef.vieworg, 16, mirrorRefdef.viewaxis[2], mirrorRefdef.vieworg );
|
|
|
|
|
|
|
|
//TBB
|
|
|
|
/*only add players to minimap scene
|
2016-04-14 12:01:56 +00:00
|
|
|
add ctf flag entities later*/
|
2011-02-18 14:31:32 +00:00
|
|
|
if (cg_rearViewRenderLevel.integer & RL_MARKS){
|
|
|
|
CG_AddMarks();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cg_rearViewRenderLevel.integer & RL_SMOKE){
|
|
|
|
CG_AddLocalEntities();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (cg_rearViewRenderLevel.integer & RL_PLAYERS || cg_rearViewRenderLevel.integer & RL_OBJECTS){
|
|
|
|
for (i = 0; i < cg.snap->numEntities; i++){
|
|
|
|
if (!(cg_rearViewRenderLevel.integer & RL_OBJECTS)){
|
|
|
|
// skip non-players
|
|
|
|
if ( cg.snap->entities[i].eType != ET_PLAYER ) continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(cg_rearViewRenderLevel.integer & RL_PLAYERS)){
|
|
|
|
// skip players
|
|
|
|
if ( cg.snap->entities[i].eType == ET_PLAYER ) continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: dont re-lerp entity
|
|
|
|
CG_AddCEntity( &cg_entities[ cg.snap->entities[ i ].number ] );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//trap_R_RenderScene( &cg.mirrorRefdef );
|
|
|
|
trap_R_RenderScene( &cg.mmapRefdef );
|
|
|
|
CG_DrawPic( mx, my, mw, mh, cgs.media.MMapShader );
|
|
|
|
}
|
|
|
|
//TBB FIN
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
CG_DrawArrowToCheckpoint
|
|
|
|
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
static float CG_DrawArrowToCheckpoint( float y ) {
|
|
|
|
centity_t *cent;
|
|
|
|
//vec3_t dir;
|
|
|
|
vec3_t forward, origin, angles;
|
|
|
|
int i;
|
|
|
|
float angle1, angle2, angleDiff;
|
|
|
|
int x, w;
|
|
|
|
float fx, fy, fw, fh;
|
|
|
|
float *color;
|
|
|
|
refdef_t refdef;
|
|
|
|
refEntity_t ent;
|
|
|
|
vec3_t mins, maxs, v;
|
|
|
|
|
|
|
|
if (cg_entities[cg.snap->ps.clientNum].finishRaceTime)
|
|
|
|
return y;
|
|
|
|
|
ioquake3 resync to revision 2369 from 2317.
Some revision messages:
Cache servers for each master server in q3_ui, otherwise servers from last updated master for shown for all Internet# sources.
Play correct team sounds when in spectator mode and following a player.
Check last listener number instead of clc.clientNum in S_AL_HearingThroughEntity so sound work correctly when spectate following a client. (Related to bug 5741.)
When in third person, don't play player's sounds as full volume in Base sound system. OpenAL already does this. (Related to bug 5741.)
really fix the confusion with game entity and refentity numbers
to further reduce confusion, rename constants like MAX_ENTITIES to MAX_REFENTITIES
Added Rend2, an alternate renderer. (Bug #4358)
Fix restoring fs_game when default.cfg is missing.
Fix restoring old fs_game upon leaving a server. Patch by Ensiform.
Change more operator commands to require sv_running to be usable. Patch by Ensiform.
Fix some "> MAX_*" to be ">= MAX_*".
Fix follow command to find clients whose name begins with a number.
Fix up "gc" command, make it more like "tell". Based on patch by Ensiform.
Add usage messages for gc, tell, vtell, and votell commands.
Check player names in gc, tell, vtell, and votell commands.
#5799 - Change messagemode text box to display colors like in console input box.
Improve "play" command, based on a patch from Ensiform.
Check for invalid filename in OpenAL's RegisterSound function.
Changed Base sound system to warn not error when sound filename is empty or too long.
Remove references to non-existent functions CM_MarkFragments and CM_LerpTag.
2012-12-06 07:07:19 +00:00
|
|
|
for (i = 0; i < MAX_GENTITIES; i++){
|
2011-02-18 14:31:32 +00:00
|
|
|
cent = &cg_entities[i];
|
|
|
|
if (cent->currentState.eType != ET_CHECKPOINT) continue;
|
|
|
|
if (cent->currentState.weapon != cg.snap->ps.stats[STAT_NEXT_CHECKPOINT]) continue;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
ioquake3 resync to revision 2369 from 2317.
Some revision messages:
Cache servers for each master server in q3_ui, otherwise servers from last updated master for shown for all Internet# sources.
Play correct team sounds when in spectator mode and following a player.
Check last listener number instead of clc.clientNum in S_AL_HearingThroughEntity so sound work correctly when spectate following a client. (Related to bug 5741.)
When in third person, don't play player's sounds as full volume in Base sound system. OpenAL already does this. (Related to bug 5741.)
really fix the confusion with game entity and refentity numbers
to further reduce confusion, rename constants like MAX_ENTITIES to MAX_REFENTITIES
Added Rend2, an alternate renderer. (Bug #4358)
Fix restoring fs_game when default.cfg is missing.
Fix restoring old fs_game upon leaving a server. Patch by Ensiform.
Change more operator commands to require sv_running to be usable. Patch by Ensiform.
Fix some "> MAX_*" to be ">= MAX_*".
Fix follow command to find clients whose name begins with a number.
Fix up "gc" command, make it more like "tell". Based on patch by Ensiform.
Add usage messages for gc, tell, vtell, and votell commands.
Check player names in gc, tell, vtell, and votell commands.
#5799 - Change messagemode text box to display colors like in console input box.
Improve "play" command, based on a patch from Ensiform.
Check for invalid filename in OpenAL's RegisterSound function.
Changed Base sound system to warn not error when sound filename is empty or too long.
Remove references to non-existent functions CM_MarkFragments and CM_LerpTag.
2012-12-06 07:07:19 +00:00
|
|
|
if (i == MAX_GENTITIES)
|
2011-02-18 14:31:32 +00:00
|
|
|
return y; // no checkpoints found
|
|
|
|
|
|
|
|
// VectorSubtract(cent->currentState.origin, cg.predictedPlayerState.origin, dir);
|
|
|
|
// angle2 = vectoyaw(dir);
|
|
|
|
|
|
|
|
// find the distance from the edge of the bounding box
|
|
|
|
trap_R_ModelBounds( cgs.inlineDrawModel[cent->currentState.modelindex], mins, maxs );
|
|
|
|
|
|
|
|
// if the checkpoint was one with no target then mins and maxs are relative to the origin
|
|
|
|
if( cent->currentState.frame == 0 )
|
|
|
|
{
|
|
|
|
VectorAdd( mins, cent->currentState.origin, mins );
|
|
|
|
VectorAdd( maxs, cent->currentState.origin, maxs );
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( i = 0 ; i < 3 ; i++ ) {
|
|
|
|
if ( cg.predictedPlayerState.origin[i] < mins[i] ) {
|
|
|
|
v[i] = mins[i] - cg.predictedPlayerState.origin[i];
|
|
|
|
} else if ( cg.predictedPlayerState.origin[i] > maxs[i] ) {
|
|
|
|
v[i] = maxs[i] - cg.predictedPlayerState.origin[i];
|
|
|
|
} else {
|
|
|
|
v[i] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( v[0] == 0 && v[1] == 0 && v[2] == 0 )
|
|
|
|
angle2 = cg.predictedPlayerState.viewangles[YAW];
|
|
|
|
else
|
|
|
|
angle2 = vectoyaw(v);
|
|
|
|
|
|
|
|
if (cg_checkpointArrowMode.integer == 1){
|
|
|
|
AngleVectors(cg.refdefViewAngles, forward, NULL, NULL);
|
|
|
|
angle1 = vectoyaw(forward);
|
|
|
|
|
|
|
|
angleDiff = AngleDifference(angle1, angle2);
|
|
|
|
|
|
|
|
// draw arrow:
|
|
|
|
VectorSet(origin, 80, 0, 20);
|
|
|
|
VectorClear(angles);
|
|
|
|
angles[YAW] = -angleDiff;
|
|
|
|
|
|
|
|
fx = 320 - 64;
|
|
|
|
fy = 16;
|
|
|
|
fw = 128;
|
|
|
|
fh = 96;
|
|
|
|
CG_AdjustFrom640( &fx, &fy, &fw, &fh );
|
|
|
|
|
|
|
|
memset( &refdef, 0, sizeof( refdef ) );
|
|
|
|
|
|
|
|
memset( &ent, 0, sizeof( ent ) );
|
|
|
|
AnglesToAxis( angles, ent.axis );
|
|
|
|
VectorCopy( origin, ent.origin );
|
|
|
|
VectorCopy( origin, ent.lightingOrigin );
|
|
|
|
ent.hModel = cgs.media.checkpointArrow;
|
|
|
|
// ent.customSkin = trap_R_RegisterShader("gfx/hud/arrow");
|
|
|
|
|
|
|
|
ent.renderfx = RF_NOSHADOW; // no stencil shadows
|
|
|
|
|
|
|
|
refdef.rdflags = RDF_NOWORLDMODEL;
|
|
|
|
|
|
|
|
vectoangles( origin, angles );
|
|
|
|
AnglesToAxis( angles, refdef.viewaxis );
|
|
|
|
|
|
|
|
refdef.fov_x = 40;
|
|
|
|
refdef.fov_y = 30;
|
|
|
|
|
|
|
|
refdef.x = fx;
|
|
|
|
refdef.y = fy;
|
|
|
|
refdef.width = fw;
|
|
|
|
refdef.height = fh;
|
|
|
|
|
|
|
|
refdef.time = cg.time;
|
|
|
|
|
|
|
|
trap_R_ClearScene();
|
|
|
|
trap_R_AddRefEntityToScene( &ent );
|
|
|
|
trap_R_RenderScene( &refdef );
|
|
|
|
}
|
|
|
|
//end draw arrow
|
|
|
|
|
|
|
|
AngleVectors(cg.predictedPlayerEntity.lerpAngles, forward, NULL, NULL);
|
|
|
|
angle1 = vectoyaw(forward);
|
|
|
|
|
|
|
|
angleDiff = AngleDifference(angle1, angle2);
|
|
|
|
|
|
|
|
// if (VectorLength(dir) < 20.0f)
|
|
|
|
// return y;
|
|
|
|
|
|
|
|
if (fabs(angleDiff) > 100){
|
|
|
|
cg.wrongWayTime = cg.time;
|
|
|
|
if( !cg.wrongWayStartTime )
|
|
|
|
cg.wrongWayStartTime = cg.time;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
cg.wrongWayStartTime = 0;
|
|
|
|
|
|
|
|
if( !cg.wrongWayStartTime || cg.wrongWayStartTime > cg.time - 2000 )
|
|
|
|
return y;
|
|
|
|
|
|
|
|
w = BIGCHAR_WIDTH * CG_DrawStrlen( "WRONG WAY!" );
|
|
|
|
x = ( SCREEN_WIDTH - w ) / 2;
|
|
|
|
|
|
|
|
color = CG_FadeColor( cg.wrongWayTime, 300 );
|
|
|
|
if ( !color ) {
|
|
|
|
return y;
|
|
|
|
}
|
|
|
|
trap_R_SetColor( color );
|
|
|
|
|
|
|
|
// if (cg_developer.integer)
|
|
|
|
// CG_Draw3DLine( cent->currentState.origin, cg.snap->ps.origin );
|
|
|
|
|
|
|
|
CG_DrawStringExt( x, SCREEN_HEIGHT * .30, "WRONG WAY!", color, qfalse, qtrue,
|
|
|
|
BIGCHAR_WIDTH, (int)(BIGCHAR_WIDTH * 1.5), 0 );
|
|
|
|
|
|
|
|
return y;
|
|
|
|
}
|
|
|
|
|
|
|
|
// takes a 3d coord and change it to screen coords
|
|
|
|
/*
|
|
|
|
// Thanks to Golliwog who implemented this bit of code in q3f
|
|
|
|
static float CG_SFK_AngleToCoord( float angle, int coordRange, float fov, qboolean reverseCoord ){
|
|
|
|
// Take an angle and return the coord it maps to (may be out of visible range)
|
|
|
|
// The conversion is: correct fov to degrees: (90.0 / fov), convert to radians: M_PI / 180,
|
|
|
|
// obtain tangent (results in -1 - 1, at least in visible coords). The first two steps can
|
|
|
|
// be combined, hence the M_PI * 0.5f / fov.
|
|
|
|
|
|
|
|
angle = tan( angle * M_PI * 0.5f / fov );
|
|
|
|
angle = coordRange * (reverseCoord ? (1.0f - angle) : (1.0f + angle));
|
|
|
|
return( angle );
|
|
|
|
}
|
|
|
|
|
|
|
|
code:
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
angles[PITCH] = AngleNormalize180( angles[PITCH] - cg.refdefViewAngles[PITCH] );
|
|
|
|
adjustedY = CG_SFK_AngleToCoord( angles[PITCH], 240, cg.refdef.fov_y, qfalse );
|
|
|
|
angles[YAW] = AngleNormalize180( angles[YAW] - cg.refdefViewAngles[YAW] );
|
|
|
|
adjustedX = CG_SFK_AngleToCoord( angles[YAW], 320, cg.refdef.fov_x, qtrue );
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
CG_DrawTimes
|
|
|
|
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
static float CG_DrawTimes( float y ) {
|
|
|
|
centity_t *cent;
|
|
|
|
int lapTime;
|
|
|
|
int totalTime;
|
|
|
|
int x;
|
|
|
|
char s[128];
|
|
|
|
char *time;
|
|
|
|
|
|
|
|
//ps = &cg.snap->ps;
|
|
|
|
cent = &cg_entities[cg.snap->ps.clientNum];
|
|
|
|
|
|
|
|
if ( cent->finishRaceTime ){
|
|
|
|
lapTime = cent->finishRaceTime - cent->startLapTime;
|
|
|
|
totalTime = cent->finishRaceTime - cent->startRaceTime;
|
|
|
|
|
|
|
|
}
|
|
|
|
else if ( cent->startRaceTime ){
|
|
|
|
lapTime = cg.time - cent->startLapTime;
|
|
|
|
totalTime = cg.time - cent->startRaceTime;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
lapTime = 0;
|
|
|
|
totalTime = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Best Time
|
|
|
|
//
|
|
|
|
|
|
|
|
if ( cgs.gametype != GT_DERBY ){
|
|
|
|
time = getStringForTime( cent->bestLapTime );
|
|
|
|
|
|
|
|
Com_sprintf(s, sizeof(s), "B; %s", time);
|
|
|
|
x = 600 - CG_DrawStrlen(s) * TINYCHAR_WIDTH;
|
|
|
|
CG_FillRect ( x, y, 96, 18, bgColor );
|
|
|
|
x+= 8;
|
|
|
|
|
|
|
|
y+= 4;
|
|
|
|
CG_DrawTinyDigitalStringColor( x, y, s, colorWhite);
|
|
|
|
y += TINYCHAR_HEIGHT + 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Lap Time
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (cgs.gametype != GT_DERBY){
|
|
|
|
time = getStringForTime(lapTime);
|
|
|
|
|
|
|
|
Com_sprintf(s, sizeof(s), "L: %s", time);
|
|
|
|
x = 600 - CG_DrawStrlen(s) * TINYCHAR_WIDTH;
|
|
|
|
CG_FillRect( x, y, 96, 18, bgColor );
|
|
|
|
x+= 8;
|
|
|
|
|
|
|
|
y+= 4;
|
|
|
|
CG_DrawTinyDigitalStringColor( x, y, s, colorWhite);
|
|
|
|
y += TINYCHAR_HEIGHT + 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Total Time
|
|
|
|
//
|
|
|
|
|
|
|
|
time = getStringForTime(totalTime);
|
|
|
|
|
|
|
|
/*
|
|
|
|
Com_sprintf(s, sizeof(s), "TOTAL TIME: %s", time);
|
|
|
|
x = 630 - CG_DrawStrlen(s) * SMALLCHAR_WIDTH;
|
|
|
|
|
|
|
|
CG_DrawSmallStringColor( x, y, s, colors[0]);
|
|
|
|
y += SMALLCHAR_HEIGHT;
|
|
|
|
*/
|
|
|
|
|
|
|
|
Com_sprintf(s, sizeof(s), "T: %s", time);
|
|
|
|
|
|
|
|
x = 636 - 96;
|
|
|
|
CG_FillRect( x, y, 96, 18, bgColor );
|
|
|
|
x += 8;
|
|
|
|
|
|
|
|
y += 4;
|
|
|
|
CG_DrawTinyDigitalStringColor( x, y, s, colorWhite);
|
|
|
|
y += TINYCHAR_HEIGHT + 4;
|
|
|
|
|
|
|
|
return y;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
CG_DrawLaps
|
|
|
|
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
static float CG_DrawLaps( float y ) {
|
|
|
|
centity_t *cent;
|
|
|
|
//playerState_t *ps;
|
|
|
|
int curLap;
|
|
|
|
int numLaps;
|
|
|
|
char s[64];
|
|
|
|
int x;
|
|
|
|
|
|
|
|
//ps = &cg.snap->ps;
|
|
|
|
cent = &cg_entities[cg.snap->ps.clientNum];
|
|
|
|
|
|
|
|
curLap = cent->currentLap;
|
|
|
|
numLaps = cgs.laplimit;
|
|
|
|
|
|
|
|
Com_sprintf(s, sizeof(s), "LAP: %i/%i", curLap, numLaps);
|
|
|
|
|
|
|
|
x = 636 - 96;
|
|
|
|
CG_FillRect( x, y, 96, 18, bgColor );
|
|
|
|
x += 8;
|
|
|
|
|
|
|
|
y += 4;
|
|
|
|
CG_DrawTinyDigitalStringColor( x, y, s, colorWhite);
|
|
|
|
y += TINYCHAR_HEIGHT + 4;
|
|
|
|
|
|
|
|
return y;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
CG_DrawCurrentPosition
|
|
|
|
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
static float CG_DrawCurrentPosition( float y ) {
|
|
|
|
centity_t *cent;
|
|
|
|
//playerState_t *ps;
|
|
|
|
int pos;
|
|
|
|
char s[64];
|
|
|
|
float x, width, height;
|
|
|
|
//float foreground[4] = { 0, 0, 0.75, 1.0 };
|
|
|
|
|
|
|
|
//ps = &cg.snap->ps;
|
|
|
|
cent = &cg_entities[cg.snap->ps.clientNum];
|
|
|
|
|
|
|
|
pos = cent->currentPosition;
|
|
|
|
|
|
|
|
Com_sprintf(s, sizeof(s), "POS: ");
|
|
|
|
|
|
|
|
x = 636 - 96;
|
|
|
|
width = 96;
|
|
|
|
height = 18;
|
|
|
|
|
|
|
|
CG_FillRect( x, y, width, height, bgColor );
|
|
|
|
|
|
|
|
x += 8;
|
|
|
|
y += 4;
|
|
|
|
|
|
|
|
CG_DrawTinyDigitalStringColor( x, y, s, colorWhite);
|
|
|
|
|
|
|
|
x += TINYCHAR_WIDTH * 5;
|
|
|
|
|
|
|
|
CG_DrawTinyDigitalStringColor( x, y, va("%i/%i", pos, cgs.numRacers), colorWhite);
|
|
|
|
|
|
|
|
y += 10 + 4;
|
|
|
|
|
|
|
|
return y;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
CG_DrawCarAheadAndBehind
|
|
|
|
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
static float CG_DrawCarAheadAndBehind( float y ) {
|
|
|
|
centity_t *cent, *other;
|
|
|
|
char player[64];
|
|
|
|
int i, j, num;
|
|
|
|
float x, width, height;
|
|
|
|
int startPos, endPos;
|
|
|
|
char s[64];
|
|
|
|
float background[4] = { 0, 0, 0, 0.5 };
|
|
|
|
float selected[4] = { 0.75, 0.0, 0.0, 0.5 };
|
|
|
|
|
|
|
|
//ps = &cg.snap->ps;
|
|
|
|
cent = &cg_entities[cg.snap->ps.clientNum];
|
|
|
|
|
|
|
|
startPos = cent->currentPosition - 4 < 1 ? 1 : cent->currentPosition - 4;
|
|
|
|
endPos = startPos + 8 > cgs.numRacers ? cgs.numRacers : startPos + 8;
|
|
|
|
startPos = endPos - 8 < 1 ? 1 : endPos - 8;
|
|
|
|
|
|
|
|
x = 636 - 96;
|
|
|
|
width = 96;
|
|
|
|
height = TINYCHAR_HEIGHT;
|
|
|
|
|
|
|
|
for (i = startPos; i <= endPos; i++){
|
|
|
|
num = -1;
|
|
|
|
for (j = 0; j < cgs.maxclients; j++){
|
|
|
|
other = &cg_entities[j];
|
|
|
|
if (!other) continue;
|
|
|
|
|
|
|
|
if (other->currentPosition == i){
|
|
|
|
num = other->currentState.clientNum;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (num < 0 || num > cgs.maxclients) continue;
|
|
|
|
|
|
|
|
if (num == cent->currentState.clientNum){
|
|
|
|
CG_FillRect( x, y, width, height, selected );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
CG_FillRect( x, y, width, height, background );
|
|
|
|
}
|
|
|
|
|
|
|
|
Q_strncpyz(player, cgs.clientinfo[num].name, 16 );
|
|
|
|
Com_sprintf(s, sizeof(s), "%i-%s", cg_entities[num].currentPosition, player);
|
|
|
|
CG_DrawTinyDigitalStringColor( x, y, s, colorWhite);
|
|
|
|
|
|
|
|
y += TINYCHAR_HEIGHT;
|
|
|
|
}
|
|
|
|
|
|
|
|
return y;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
/*
|
|
|
|
=================
|
|
|
|
CG_DrawHUD_DerbyList
|
|
|
|
|
|
|
|
=================
|
|
|
|
*/
|
|
|
|
void CG_DrawHUD_DerbyList(float x, float y){
|
|
|
|
int i;
|
|
|
|
vec4_t color;
|
|
|
|
centity_t *cent;
|
|
|
|
char *time;
|
|
|
|
float playTime;
|
|
|
|
|
|
|
|
// draw heading
|
|
|
|
CG_FillRect(x, y, 536, 18, bgColor);
|
|
|
|
|
|
|
|
// name
|
|
|
|
CG_DrawTinyDigitalStringColor( x + 42, y, "PLAYER:", colorWhite);
|
|
|
|
|
|
|
|
// time
|
|
|
|
CG_DrawTinyDigitalStringColor( x + 206, y, "TIME:", colorWhite);
|
|
|
|
|
|
|
|
// dmg dealt
|
|
|
|
CG_DrawTinyDigitalStringColor( x + 294, y, "DMG DEALT:", colorWhite);
|
|
|
|
|
|
|
|
// dmg taken
|
|
|
|
CG_DrawTinyDigitalStringColor( x + 442, y, "DMG TAKEN:", colorWhite);
|
|
|
|
|
|
|
|
y += 20;
|
|
|
|
|
|
|
|
// draw top 8 players
|
|
|
|
for (i = 0; i < 8; i++){
|
|
|
|
if (cg.scores[i].scoreFlags < 0) continue; // score is not valid so skip it
|
|
|
|
|
|
|
|
cent = &cg_entities[cg.scores[i].client];
|
|
|
|
if (!cent) continue;
|
|
|
|
|
|
|
|
CG_FillRect(x, y, 536, 18, bgColor);
|
|
|
|
|
|
|
|
Vector4Copy(colorWhite, color);
|
|
|
|
if (cg.scores[i].client == cg.snap->ps.clientNum){
|
|
|
|
if (cg.snap->ps.stats[STAT_HEALTH] <= 0 || cgs.clientinfo[cg.scores[i].client].team == TEAM_SPECTATOR)
|
|
|
|
Vector4Copy(colorMdGrey, color);
|
|
|
|
}
|
|
|
|
else if (cent->currentState.eFlags & EF_DEAD || cgs.clientinfo[cg.scores[i].client].team == TEAM_SPECTATOR){
|
|
|
|
Vector4Copy(colorMdGrey, color);
|
|
|
|
}
|
|
|
|
|
|
|
|
playTime = 0;
|
|
|
|
if (cent->finishRaceTime){
|
|
|
|
playTime = cent->finishRaceTime - cent->startLapTime;
|
|
|
|
}
|
|
|
|
else if (cent->startRaceTime){
|
|
|
|
playTime = cg.time - cent->startLapTime;
|
|
|
|
}
|
|
|
|
time = getStringForTime(playTime);
|
|
|
|
|
|
|
|
// num
|
|
|
|
CG_DrawTinyDigitalStringColor( x + 6, y, va("0%i", (i+1)), color);
|
|
|
|
|
|
|
|
// name
|
|
|
|
CG_DrawTinyDigitalStringColor( x + 42, y, cgs.clientinfo[cg.scores[i].client].name, color);
|
|
|
|
|
|
|
|
// time
|
|
|
|
CG_DrawTinyDigitalStringColor( x + 192, y, time, color);
|
|
|
|
|
|
|
|
// dmg dealt
|
|
|
|
CG_DrawTinyDigitalStringColor( x + 326, y, va("%i", cg.scores[i].damageDealt), color);
|
|
|
|
|
|
|
|
// dmg taken
|
|
|
|
CG_DrawTinyDigitalStringColor( x + 474, y, va("%i", cg.scores[i].damageTaken), color);
|
|
|
|
|
|
|
|
y += 20;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
CG_DrawSpeed
|
|
|
|
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
static float CG_DrawSpeed( float y ) {
|
|
|
|
playerState_t *ps;
|
|
|
|
int vel_speed;
|
|
|
|
vec3_t forward, origin, angles, mins, maxs;
|
|
|
|
int x, yorg;
|
|
|
|
float x2, y2, w, h;
|
|
|
|
refdef_t refdef;
|
|
|
|
refEntity_t ent;
|
|
|
|
|
|
|
|
x = 630;
|
|
|
|
yorg = y;
|
|
|
|
|
|
|
|
ps = &cg.predictedPlayerState;
|
|
|
|
|
|
|
|
AngleVectors( ps->viewangles, forward, NULL, NULL );
|
|
|
|
|
|
|
|
// use actual speed
|
|
|
|
vel_speed = (int)fabs( Q3VelocityToRL( DotProduct(ps->velocity, forward) ) );
|
|
|
|
/*
|
|
|
|
#ifdef Q3_VM
|
|
|
|
if (ps->stats[STAT_GEAR] == -1)
|
|
|
|
vel_speed = (int)fabs(10.0f * Q3UnitsToRL(WHEEL_RADIUS * min(cg_entities[cg.snap->ps.clientNum].wheelSpeeds[0], cg_entities[cg.snap->ps.clientNum].wheelSpeeds[1])));
|
|
|
|
else
|
|
|
|
vel_speed = (int)fabs(10.0f * Q3UnitsToRL(WHEEL_RADIUS * max(cg_entities[cg.snap->ps.clientNum].wheelSpeeds[0], cg_entities[cg.snap->ps.clientNum].wheelSpeeds[1])));
|
|
|
|
#else
|
|
|
|
if (ps->stats[STAT_GEAR] == -1)
|
|
|
|
vel_speed = (int)fabs(Q3UnitsToRL(WHEEL_RADIUS * min(cg_entities[cg.snap->ps.clientNum].wheelSpeeds[0], cg_entities[cg.snap->ps.clientNum].wheelSpeeds[1])));
|
|
|
|
else
|
|
|
|
vel_speed = (int)fabs(Q3UnitsToRL(WHEEL_RADIUS * max(cg_entities[cg.snap->ps.clientNum].wheelSpeeds[0], cg_entities[cg.snap->ps.clientNum].wheelSpeeds[1])));
|
|
|
|
#endif
|
|
|
|
*/
|
|
|
|
|
|
|
|
// draw speedometer here
|
|
|
|
x2 = x - 96;
|
|
|
|
y2 = y - 96;
|
|
|
|
CG_DrawPic( x2, y2, 96, 96, trap_R_RegisterShaderNoMip("gfx/hud/gauge01"));
|
|
|
|
|
|
|
|
|
|
|
|
// draw digital speed
|
|
|
|
x -= 48 + (CG_DrawStrlen(va("%i", vel_speed)) * SMALLCHAR_WIDTH) / 2;
|
|
|
|
y -= 28;
|
2021-03-26 22:43:44 +00:00
|
|
|
CG_DrawSmallDigitalStringColor( x, y, va("%i", vel_speed), colorWhite);
|
2011-02-18 14:31:32 +00:00
|
|
|
|
|
|
|
// draw needle
|
|
|
|
|
|
|
|
w = h = 96;
|
|
|
|
CG_AdjustFrom640( &x2, &y2, &w, &h );
|
|
|
|
|
|
|
|
memset( &refdef, 0, sizeof( refdef ) );
|
|
|
|
memset( &ent, 0, sizeof( ent ) );
|
|
|
|
|
|
|
|
ent.hModel = trap_R_RegisterModel("gfx/hud/needle.md3");
|
|
|
|
ent.customShader = trap_R_RegisterShader("gfx/hud/needle01");
|
|
|
|
ent.renderfx = RF_NOSHADOW; // no stencil shadows
|
|
|
|
|
|
|
|
trap_R_ModelBounds(ent.hModel, mins, maxs);
|
|
|
|
|
|
|
|
// origin[2] = -0.5 * ( mins[2] + maxs[2] );
|
|
|
|
origin[2] = 0;
|
|
|
|
origin[1] = 0.5 * ( mins[1] + maxs[1] );
|
|
|
|
origin[0] = ( maxs[2] - mins[2] ) / 0.268;
|
|
|
|
|
|
|
|
VectorClear(angles);
|
|
|
|
angles[YAW] -= 90;
|
|
|
|
angles[PITCH] = -150.0f + (300.0f * vel_speed / 200.0f);
|
|
|
|
AnglesToAxis( angles, ent.axis );
|
|
|
|
VectorCopy(origin, ent.origin);
|
|
|
|
|
|
|
|
refdef.rdflags = RDF_NOWORLDMODEL;
|
|
|
|
|
|
|
|
AxisClear( refdef.viewaxis );
|
|
|
|
|
|
|
|
refdef.fov_x = 30;
|
|
|
|
refdef.fov_y = 30;
|
|
|
|
|
|
|
|
refdef.x = x2;
|
|
|
|
refdef.y = y2;
|
|
|
|
refdef.width = w;
|
|
|
|
refdef.height = h;
|
|
|
|
|
|
|
|
refdef.time = cg.time;
|
|
|
|
|
|
|
|
trap_R_ClearScene();
|
|
|
|
trap_R_AddRefEntityToScene( &ent );
|
|
|
|
trap_R_RenderScene( &refdef );
|
|
|
|
|
|
|
|
// draw center here
|
|
|
|
x = 630;
|
|
|
|
y = yorg;
|
|
|
|
|
|
|
|
x -= 60;
|
|
|
|
y -= 60;
|
|
|
|
CG_DrawPic( x, y, 24, 24, trap_R_RegisterShaderNoMip("gfx/hud/center01"));
|
|
|
|
|
|
|
|
// draw gear over center of gauge
|
|
|
|
if ( cg.predictedPlayerState.stats[STAT_GEAR] == -1 )
|
2021-03-26 22:43:44 +00:00
|
|
|
CG_DrawSmallDigitalStringColor( x+10, y+4, "R", colorWhite);
|
2011-02-18 14:31:32 +00:00
|
|
|
else if ( cg.predictedPlayerState.stats[STAT_GEAR] == 0 )
|
2021-03-26 22:43:44 +00:00
|
|
|
CG_DrawSmallDigitalStringColor( x+10, y+4, "N", colorWhite);
|
2011-02-18 14:31:32 +00:00
|
|
|
else
|
2021-03-26 22:43:44 +00:00
|
|
|
CG_DrawSmallDigitalStringColor( x+10, y+4, va("%i", cg.predictedPlayerState.stats[STAT_GEAR]), colorWhite);
|
2011-02-18 14:31:32 +00:00
|
|
|
|
|
|
|
y -= 39;
|
|
|
|
|
|
|
|
y -= SMALLCHAR_HEIGHT;
|
|
|
|
|
|
|
|
return y;
|
|
|
|
}
|
|
|
|
|
|
|
|
static float CG_DrawSDKMessage( float y ) {
|
|
|
|
int x, w;
|
|
|
|
vec4_t bg_color;
|
|
|
|
|
|
|
|
switch (cgs.clientinfo[cg.snap->ps.clientNum].team){
|
|
|
|
case TEAM_RED:
|
|
|
|
Vector4Copy(colorRed, bg_color);
|
|
|
|
bg_color[3] = 0.5;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TEAM_BLUE:
|
|
|
|
Vector4Copy(colorBlue, bg_color);
|
|
|
|
bg_color[3] = 0.5;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TEAM_GREEN:
|
|
|
|
Vector4Copy(colorGreen, bg_color);
|
|
|
|
bg_color[3] = 0.5;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TEAM_YELLOW:
|
|
|
|
Vector4Copy(colorYellow, bg_color);
|
|
|
|
bg_color[3] = 0.5;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
Vector4Copy(bgColor, bg_color);
|
|
|
|
}
|
|
|
|
|
|
|
|
x = 4;
|
2021-02-18 08:12:12 +00:00
|
|
|
w = (CG_DrawStrlen("Not the finished game.") * TINYCHAR_WIDTH);
|
2011-02-18 14:31:32 +00:00
|
|
|
|
|
|
|
y -= 3*TINYCHAR_HEIGHT+2;
|
|
|
|
|
|
|
|
CG_FillRect( x, y, w, 3*TINYCHAR_HEIGHT+2, bg_color );
|
|
|
|
|
2011-07-30 15:11:52 +00:00
|
|
|
CG_DrawTinyStringColor( x, y, Q3_VERSION, colorWhite);
|
2011-02-18 14:31:32 +00:00
|
|
|
y += TINYCHAR_HEIGHT;
|
2021-02-18 08:12:12 +00:00
|
|
|
CG_DrawTinyStringColor( x, y, "Beta Version", colorWhite);
|
2011-02-18 14:31:32 +00:00
|
|
|
y += TINYCHAR_HEIGHT;
|
2021-02-18 08:12:12 +00:00
|
|
|
CG_DrawTinyStringColor( x, y, "Not the finished game.", colorWhite);
|
2011-02-18 14:31:32 +00:00
|
|
|
y += TINYCHAR_HEIGHT;
|
|
|
|
|
|
|
|
y -= 3*TINYCHAR_HEIGHT+2;
|
|
|
|
|
|
|
|
return y;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
CG_DrawGear
|
|
|
|
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
static float CG_DrawGear( float y ) {
|
|
|
|
CG_DrawSmallDigitalStringColor( 560, y, va("Gear: %d", cg.predictedPlayerState.stats[STAT_GEAR]), colors[0]);
|
|
|
|
y -= SMALLCHAR_HEIGHT;
|
|
|
|
CG_DrawTinyDigitalStringColor( 560, y, va("RPM: %d", cg.predictedPlayerState.stats[STAT_RPM]), colorWhite);
|
|
|
|
y -= SMALLCHAR_HEIGHT;
|
|
|
|
return y;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
// for translating a 3d point to the screen ?
|
|
|
|
planeCameraDist = 50;
|
|
|
|
VectorSubtract(targetv, cg.refdef.viewaxis, dir);
|
|
|
|
viewdist = DotProduct(dir, cg.refdef.viewaxis[0]);
|
|
|
|
planedist = viewdist - planeCameraDist;
|
|
|
|
VectorMA(targetv, -planedist, cg.refdef.viewaxis[0], pointOnPlane);
|
|
|
|
VectorMA(pointOnPlane, -(planedist / viewdist) * DotProduct(dir, cg.refdef.viewaxis[1]), cg.refdef.viewaxis[1], pointOnPlane);
|
|
|
|
VectorMA(pointOnPlane, -(planedist / viewdist) * DotProduct(dir, cg.refdef.viewaxis[2]), cg.refdef.viewaxis[2], pointOnPlane);
|
|
|
|
*/
|
|
|
|
|
|
|
|
float CG_DrawUpperRightHUD( float y ) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
// FIXME: this should be moved somewhere else
|
|
|
|
cgs.numRacers = 0;
|
|
|
|
for ( i = 0 ; i < cgs.maxclients ; i++ ) {
|
|
|
|
if (!cgs.clientinfo[i].infoValid) continue;
|
|
|
|
if (cgs.clientinfo[i].team == TEAM_SPECTATOR) continue;
|
|
|
|
if (cg.scores[i].ping == -1) continue;
|
|
|
|
|
|
|
|
cgs.numRacers++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cgs.clientinfo[cg.snap->ps.clientNum].team != TEAM_SPECTATOR){
|
|
|
|
if (isRallyRace()){
|
|
|
|
y = CG_DrawArrowToCheckpoint( y );
|
|
|
|
y = CG_DrawTimes( y );
|
|
|
|
y = CG_DrawLaps( y );
|
|
|
|
y = CG_DrawCurrentPosition( y );
|
|
|
|
y = CG_DrawCarAheadAndBehind( y );
|
|
|
|
}
|
|
|
|
else if (cgs.gametype == GT_DERBY)
|
|
|
|
y = CG_DrawTimes( y );
|
|
|
|
// CG_DrawHUD_DerbyList(44, 130);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isRallyNonDMRace() && cgs.gametype != GT_DERBY){
|
|
|
|
y = CG_DrawScores( 636, y );
|
|
|
|
}
|
|
|
|
|
|
|
|
return y;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
float CG_DrawLowerRightHUD( float y ) {
|
|
|
|
if (cgs.clientinfo[cg.snap->ps.clientNum].team != TEAM_SPECTATOR){
|
|
|
|
y = CG_DrawSpeed( y );
|
|
|
|
// y = CG_DrawGear( y );
|
|
|
|
}
|
|
|
|
|
|
|
|
return y;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
float CG_DrawLowerLeftHUD( float y ) {
|
|
|
|
// check if there is rear ammo being displayed
|
|
|
|
int i;
|
|
|
|
|
|
|
|
y += 36;
|
|
|
|
for (i = RWP_SMOKE; i < WP_NUM_WEAPONS; i++){
|
|
|
|
if (cg.snap->ps.stats[STAT_WEAPONS] & ( 1 << i )){
|
|
|
|
if (cg.snap->ps.ammo[ i ]){
|
|
|
|
y -= 36;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Comment this out in the full release Version
|
|
|
|
|
|
|
|
y = CG_DrawSDKMessage( y );
|
|
|
|
|
|
|
|
return y;
|
|
|
|
}
|