summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cgame/cg_consolecmds.c25
-rw-r--r--src/cgame/cg_draw.c116
-rw-r--r--src/cgame/cg_drawtools.c53
-rw-r--r--src/cgame/cg_local.h17
-rw-r--r--src/cgame/cg_main.c4
-rw-r--r--src/ui/ui_shared.c3
6 files changed, 208 insertions, 10 deletions
diff --git a/src/cgame/cg_consolecmds.c b/src/cgame/cg_consolecmds.c
index 697b0e98..d28c4211 100644
--- a/src/cgame/cg_consolecmds.c
+++ b/src/cgame/cg_consolecmds.c
@@ -188,6 +188,30 @@ static void CG_TellAttacker_f( void )
trap_SendClientCommand( command );
}
+static void CG_SquadMark_f( void )
+{
+ centity_t *cent;
+ vec3_t start, end;
+ trace_t trace;
+
+ // Find the player we are looking at
+ VectorCopy( cg.refdef.vieworg, start );
+ VectorMA( start, 131072, cg.refdef.viewaxis[ 0 ], end );
+ CG_Trace( &trace, start, vec3_origin, vec3_origin, end,
+ cg.snap->ps.clientNum, CONTENTS_SOLID|CONTENTS_BODY );
+ if( trace.entityNum >= MAX_CLIENTS )
+ return;
+
+ // Only mark teammates
+ cent = cg_entities + trace.entityNum;
+ if( cent->currentState.eType != ET_PLAYER ||
+ cgs.clientinfo[ trace.entityNum ].team !=
+ cg.snap->ps.stats[ STAT_PTEAM ] )
+ return;
+
+ cent->pe.squadMarked = !cent->pe.squadMarked;
+}
+
typedef struct
{
char *cmd;
@@ -219,6 +243,7 @@ static consoleCommand_t commands[ ] =
{ "destroyTestPS", CG_DestroyTestPS_f },
{ "testTS", CG_TestTS_f },
{ "destroyTestTS", CG_DestroyTestTS_f },
+ { "squadmark", CG_SquadMark_f },
};
diff --git a/src/cgame/cg_draw.c b/src/cgame/cg_draw.c
index 5ae1093a..31e619c7 100644
--- a/src/cgame/cg_draw.c
+++ b/src/cgame/cg_draw.c
@@ -2249,7 +2249,7 @@ static void CG_DrawCrosshairNames( rectDef_t *rect, float scale, int textStyle )
CG_ScanForCrosshairEntity( );
// draw the name of the player being looked at
- color = CG_FadeColor( cg.crosshairClientTime, 1000 );
+ color = CG_FadeColor( cg.crosshairClientTime, CROSSHAIR_CLIENT_TIMEOUT );
if( !color )
{
trap_R_SetColor( NULL );
@@ -2263,6 +2263,116 @@ static void CG_DrawCrosshairNames( rectDef_t *rect, float scale, int textStyle )
trap_R_SetColor( NULL );
}
+/*
+===============
+CG_DrawSquadMarkers
+===============
+*/
+#define SQUAD_MARKER_W 16.0f
+#define SQUAD_MARKER_H 8.0f
+#define SQUAD_MARKER_BORDER 8.0f
+static void CG_DrawSquadMarkers( vec4_t color )
+{
+ centity_t *cent;
+ vec3_t origin, maxs;
+ qhandle_t shader;
+ float x, y, w, h, distance, scale, u1 = 0.0f, v1 = 0.0f, u2 = 1.0f, v2 = 1.0f;
+ int i, class;
+ qboolean vertical = qfalse, flip = qfalse;
+
+ if( cg.snap->ps.persistant[ PERS_TEAM ] == TEAM_SPECTATOR )
+ return;
+
+ trap_R_SetColor( color );
+ for( i = 0; i < cg.snap->numEntities; i++ )
+ {
+ cent = cg_entities + cg.snap->entities[ i ].number;
+ if( cent->currentState.eType != ET_PLAYER ||
+ cgs.clientinfo[ i ].team != cg.snap->ps.stats[ STAT_PTEAM ] ||
+ !cent->pe.squadMarked )
+ continue;
+
+ // Find where on screen the player is
+ VectorCopy( cent->lerpOrigin, origin );
+ origin[ 2 ] += ( ( cent->currentState.solid >> 16 ) & 255 ) - 30;
+ if( !CG_WorldToScreenWrap( origin, &x, &y ) )
+ continue;
+
+ // Scale the size of the marker with distance
+ distance = Distance( cent->lerpOrigin, cg.refdef.vieworg );
+ if( !distance )
+ continue;
+
+ scale = 200.0f / distance;
+
+ if( scale > 1.0f )
+ scale = 1.0f;
+
+ if( scale < 0.25f )
+ scale = 0.25f;
+
+ // Don't let the marker go off-screen
+ if( x < SQUAD_MARKER_BORDER )
+ {
+ x = SQUAD_MARKER_BORDER;
+ vertical = qtrue;
+ flip = qfalse;
+ }
+ else if( x > 640.0f - SQUAD_MARKER_BORDER )
+ {
+ x = 640.0f - SQUAD_MARKER_BORDER;
+ vertical = qtrue;
+ flip = qtrue;
+ }
+
+ if( y < SQUAD_MARKER_BORDER )
+ {
+ y = SQUAD_MARKER_BORDER;
+ vertical = qfalse;
+ flip = qtrue;
+ }
+ else if( y > 480.0f - SQUAD_MARKER_BORDER )
+ {
+ y = 480.0f - SQUAD_MARKER_BORDER;
+ vertical = qfalse;
+ flip = qfalse;
+ }
+
+ // Draw the marker
+ if( vertical )
+ {
+ shader = cgs.media.squadMarkerV;
+
+ if( flip )
+ {
+ u1 = 1.0f;
+ u2 = 0.0f;
+ }
+
+ w = SQUAD_MARKER_H * scale;
+ h = SQUAD_MARKER_W * scale;
+ }
+ else
+ {
+ shader = cgs.media.squadMarkerH;
+
+ if( flip )
+ {
+ v1 = 1.0f;
+ v2 = 0.0f;
+ }
+
+ w = SQUAD_MARKER_W * scale;
+ h = SQUAD_MARKER_H * scale;
+ }
+
+ CG_AdjustFrom640( &x, &y, &w, &h );
+ trap_R_DrawStretchPic( x - w / 2, y - h / 2, w, h, u1, v1, u2, v2,
+ shader );
+ }
+
+ trap_R_SetColor( NULL );
+}
/*
===============
@@ -2391,6 +2501,9 @@ void CG_OwnerDraw( float x, float y, float w, float h, float text_x,
case CG_HUMANS_SCORE_LABEL:
CG_DrawTeamLabel( &rect, PTE_HUMANS, text_x, text_y, color, scale, textalign, textvalign, textStyle );
break;
+ case CG_SQUAD_MARKERS:
+ CG_DrawSquadMarkers( color );
+ break;
//loading screen
case CG_LOAD_LEVELSHOT:
@@ -2977,7 +3090,6 @@ static void CG_Draw2D( void )
CG_DrawLighting( );
-
defaultMenu = Menus_FindByName( "default_hud" );
if( cg.snap->ps.persistant[ PERS_TEAM ] == TEAM_SPECTATOR )
diff --git a/src/cgame/cg_drawtools.c b/src/cgame/cg_drawtools.c
index 06ae0713..fb34f991 100644
--- a/src/cgame/cg_drawtools.c
+++ b/src/cgame/cg_drawtools.c
@@ -349,6 +349,59 @@ qboolean CG_WorldToScreen( vec3_t point, float *x, float *y )
/*
================
+CG_WorldToScreenWrap
+================
+*/
+qboolean CG_WorldToScreenWrap( vec3_t point, float *x, float *y )
+{
+ vec3_t trans;
+ float px, py, dotForward, dotRight, dotUp, distance, propX, propY;
+
+ px = tan( cg.refdef.fov_x * M_PI / 360.0f );
+ py = tan( cg.refdef.fov_y * M_PI / 360.0f );
+
+ VectorSubtract( point, cg.refdef.vieworg, trans );
+
+ dotForward = DotProduct( trans, cg.refdef.viewaxis[ 0 ] );
+ dotRight = DotProduct( trans, cg.refdef.viewaxis[ 1 ] );
+ dotUp = DotProduct( trans, cg.refdef.viewaxis[ 2 ] );
+
+ distance = abs( dotForward );
+ propX = dotRight / ( distance * px );
+ propY = dotUp / ( distance * py );
+
+ // The distance along the forward axis does not make sense once the point
+ // moves off-screen so we need to use either the side or the up axis instead
+ if( propX < -1.0f || propX > 1.0f )
+ {
+ distance = abs( dotRight ) / px;
+ propY = dotUp / ( distance * py );
+ }
+ if( propY < -1.0f || propY > 1.0f )
+ {
+ distance = abs( dotUp ) / py;
+ propX = dotRight / ( distance * px );
+ }
+
+ if( x )
+ *x = 320 - propX * 320;
+ if( y )
+ *y = 240 - propY * 240;
+
+ // Snap to the edge of the screen when the point is behind us
+ if( dotForward < 0.f && *x > 0 && *x < 640 && *y > 0 && *y < 480 )
+ {
+ if( abs( *x - 320 ) > abs( *y - 240 ) )
+ *x = *x <= 320 ? 0.0f : 640;
+ else
+ *y = *y <= 240 ? 0.0f : 480;
+ }
+
+ return qtrue;
+}
+
+/*
+================
CG_KeyBinding
================
*/
diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h
index 74e43bea..891edbd4 100644
--- a/src/cgame/cg_local.h
+++ b/src/cgame/cg_local.h
@@ -572,6 +572,8 @@ typedef struct
lerpFrame_t legs, torso, flag, nonseg;
int painTime;
int painDirection; // flip from 0 to 1
+
+ qboolean squadMarked; // player has been marked as a squadmember
// machinegun spinning
float barrelAngle;
@@ -713,7 +715,7 @@ typedef struct
char name[ MAX_QPATH ];
pTeam_t team;
-
+
vec3_t color1;
vec3_t color2;
@@ -725,12 +727,6 @@ typedef struct
int handicap;
- int medkitUsageTime;
- int invulnerabilityStartTime;
- int invulnerabilityStopTime;
-
- int breathPuffTime;
-
// when clientinfo is changed, the loading of models/skins/sounds
// can be deferred until you are dead, to prevent hitches in
// gameplay
@@ -901,6 +897,9 @@ typedef struct
#define NUM_SAVED_STATES ( CMD_BACKUP + 2 )
+// After this many msec the crosshair name fades out completely
+#define CROSSHAIR_CLIENT_TIMEOUT 1000
+
typedef struct
{
int clientFrame; // incremented each frame
@@ -1284,6 +1283,9 @@ typedef struct
qhandle_t healthCross3X;
qhandle_t healthCrossMedkit;
qhandle_t healthCrossPoisoned;
+
+ qhandle_t squadMarkerH;
+ qhandle_t squadMarkerV;
} cgMedia_t;
typedef struct
@@ -1606,6 +1608,7 @@ void CG_DrawRect( float x, float y, float width, float height, float size
void CG_DrawSides(float x, float y, float w, float h, float size);
void CG_DrawTopBottom(float x, float y, float w, float h, float size);
qboolean CG_WorldToScreen( vec3_t point, float *x, float *y );
+qboolean CG_WorldToScreenWrap( vec3_t point, float *x, float *y );
char *CG_KeyBinding( const char *bind );
diff --git a/src/cgame/cg_main.c b/src/cgame/cg_main.c
index 67db0a61..c094ffee 100644
--- a/src/cgame/cg_main.c
+++ b/src/cgame/cg_main.c
@@ -852,6 +852,10 @@ static void CG_RegisterGraphics( void )
cgs.media.healthCross3X = trap_R_RegisterShader( "ui/assets/neutral/cross3.tga" );
cgs.media.healthCrossMedkit = trap_R_RegisterShader( "ui/assets/neutral/cross_medkit.tga" );
cgs.media.healthCrossPoisoned = trap_R_RegisterShader( "ui/assets/neutral/cross_poison.tga" );
+
+ // squad markers
+ cgs.media.squadMarkerH = trap_R_RegisterShader( "ui/assets/neutral/squad_h" );
+ cgs.media.squadMarkerV = trap_R_RegisterShader( "ui/assets/neutral/squad_v" );
cgs.media.upgradeClassIconShader = trap_R_RegisterShader( "icons/icona_upgrade.tga" );
diff --git a/src/ui/ui_shared.c b/src/ui/ui_shared.c
index 8351f6fd..4513eb85 100644
--- a/src/ui/ui_shared.c
+++ b/src/ui/ui_shared.c
@@ -5110,7 +5110,8 @@ static bind_t g_bindings[] =
{ "messagemode", -1, -1, -1, -1 },
{ "messagemode2", -1, -1, -1, -1 },
{ "messagemode3", -1, -1, -1, -1 },
- { "messagemode4", -1, -1, -1, -1 }
+ { "messagemode4", -1, -1, -1, -1 },
+ { "squadmark", 'k', -1, -1, -1 },
};