void CG_DrawChatbox( void ) { int i = MAX_CHATBOX_ENTRIES-MIN( cg_chatboxLineCount->integer, chatbox.numActiveLines ); int numLines = 0; int done = 0; if ( CG_ChatboxActive() ) { const char *pre = chat_team ? "Team: %s" : "Say: %s"; CG_Text_Paint( CHATBOX_POS_X, CHATBOX_POS_Y + (CHATBOX_LINE_HEIGHT*cg_chatboxLineCount->integer), CHATBOX_FONT_SCALE, &g_color_table[ColorIndex(COLOR_WHITE)], va( pre, chatField.buffer ), 0, 0, ITEM_TEXTSTYLE_SHADOWED ); } if ( cg.scoreBoardShowing && !(cg.snap && cg.snap->ps.pm_type == PM_INTERMISSION) ) return; //i is the ideal index. Now offset for scrolling i += chatbox.scrollAmount; if ( chatbox.numActiveLines == 0 ) return; if ( chatbox.scrollAmount < 0 && CG_ChatboxActive() ) CG_Text_Paint( CHATBOX_POS_X, CHATBOX_POS_Y - (CHATBOX_LINE_HEIGHT), CHATBOX_FONT_SCALE, &g_color_table[ColorIndex(COLOR_WHITE)], va( "^3Scrolled lines: ^5%i\n", chatbox.scrollAmount*-1 ), 0, 0, ITEM_TEXTSTYLE_SHADOWED ); for ( done = 0; done<cg_chatboxLineCount->integer && i<MAX_CHATBOX_ENTRIES; i++, done++ ) { chatEntry_t *chat = &chatbox.chatBuffer[i]; if ( chat->isUsed ) { if ( chat->time >= cg.time-cg_chatboxMsgTime->integer || (chatbox.scrollAmount && CG_ChatboxActive()) || CG_ChatboxActive() ) { CG_Text_Paint( CHATBOX_POS_X, CHATBOX_POS_Y + (CHATBOX_LINE_HEIGHT * numLines), CHATBOX_FONT_SCALE, &g_color_table[ColorIndex(COLOR_WHITE)], chat->message, 0, 0, ITEM_TEXTSTYLE_SHADOWED ); numLines++; } } } }
static void CG_DrawFPSInfo( rectDef_t *rect, float scale, vector4 *color, qhandle_t shader, int textStyle ) { static int previousTimes[FPS_FRAMES], index, previous, lastupdate; int t, i, total, frameTime; float point = 1.0f, fps, maxFPS = 1000.0f/com_frametime->value; vector4 fpsColour = { 1.0f, 1.0f, 1.0f, 1.0f }; if ( !cg_drawFPS->boolean && !cg_debugHUD->boolean ) 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; if ( t - lastupdate > 50 ) {// don't sample faster than this lastupdate = t; previousTimes[index++ & FPS_MASK] = frameTime; } // 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.0f * (float)((float)FPS_FRAMES / (float)total); point = MIN( MAX(0.0f, fps) / MAX(IDEAL_FPS, maxFPS), 1.0f ); VectorLerp4( QCOLOR(COLOR_RED), point, QCOLOR(COLOR_GREEN), &fpsColour ); fpsColour.a = 1.0f; CG_Text_Paint( rect->x, rect->y, scale, &fpsColour, va( "%i FPS", (int)fps ), 0, 0, textStyle ); }
void CG_DrawMedal(int ownerDraw, rectDef_t *rect, float scale, vector4 *color, qhandle_t shader) { score_t *score = &cg.scores[cg.selectedScore]; float value = 0; const char *text = NULL; color->a = 0.25f; switch (ownerDraw) { case CG_ACCURACY: value = (float)score->accuracy; break; case CG_ASSISTS: value = (float)score->assistCount; break; case CG_DEFEND: value = (float)score->defendCount; break; case CG_EXCELLENT: value = (float)score->excellentCount; break; case CG_IMPRESSIVE: value = (float)score->impressiveCount; break; case CG_PERFECT: value = (float)score->perfect; break; case CG_CAPTURES: value = (float)score->captures; break; } if (value > 0) { if (ownerDraw != CG_PERFECT) { if (ownerDraw == CG_ACCURACY) { text = va("%i%%", (int)value); if (value > 50) { color->a = 1.0f; } } else { text = va("%i", (int)value); color->a = 1.0f; } } else { if (value) { color->a = 1.0f; } text = "Wow"; } } trap->R_SetColor(color); CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader ); if (text) { color->a = 1.0f; value = (float)CG_Text_Width(text, scale, 0); CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h + 10 , scale, color, text, 0, 0, 0); } trap->R_SetColor(NULL); }
void CG_DrawStringExt( int x, int y, const char *string, const vector4 *setColor, qboolean forceColor, qboolean shadow, int charWidth, int charHeight, int maxChars ) { if ( trap->R_Language_IsAsian() ) { // hack-a-doodle-do (post-release quick fix code)... // vector4 color; memcpy( &color, setColor, sizeof(color) ); // de-const it CG_Text_Paint( x, y, 1.0f, // float scale, &color, // vector4 color, string, // const char *text, 0.0f, // float adjust, 0, // int limit, shadow ? ITEM_TEXTSTYLE_SHADOWED : 0, // int style, FONT_MEDIUM // iMenuFont ); } else { vector4 color; const char *s; int xx; // draw the drop shadow if ( shadow ) { color.r = color.g = color.b = 0; color.a = setColor->a; trap->R_SetColor( &color ); s = string; xx = x; while ( *s ) { if ( Q_IsColorString( s ) ) { s += 2; continue; } CG_DrawChar( xx + 2, y + 2, charWidth, charHeight, *s ); xx += charWidth; s++; } } // draw the colored text s = string; xx = x; trap->R_SetColor( setColor ); while ( *s ) { if ( Q_IsColorString( s ) ) { if ( !forceColor ) { memcpy( &color, &g_color_table[ColorIndex( *(s + 1) )], sizeof(color) ); color.a = setColor->a; trap->R_SetColor( &color ); } s += 2; continue; } CG_DrawChar( xx, y, charWidth, charHeight, *s ); xx += charWidth; s++; } trap->R_SetColor( NULL ); } }
void UI_DrawScaledProportionalString( int x, int y, const char* str, int style, const vector4 *color, float scale ) { // having all these different style defines (1 for UI, one for CG, and now one for the re->font stuff) // is dumb, but for now... // int iStyle = 0; switch ( style & (UI_LEFT | UI_CENTER | UI_RIGHT) ) { default: case UI_LEFT: // nada... break; case UI_CENTER: x -= CG_Text_Width( str, scale, FONT_MEDIUM ) / 2; break; case UI_RIGHT: x -= CG_Text_Width( str, scale, FONT_MEDIUM ) / 2; break; } if ( style & UI_DROPSHADOW ) iStyle = ITEM_TEXTSTYLE_SHADOWED; else if ( style & (UI_BLINK | UI_PULSE) ) iStyle = ITEM_TEXTSTYLE_BLINK; CG_Text_Paint( x, y, scale, color, str, 0, 0, iStyle, FONT_MEDIUM ); }
static void CG_DrawPlayerAmmoValue(rectDef_t *rect, float scale, vector4 *color, qhandle_t shader, int textStyle) { char num[16]; int value; float width; centity_t *cent; playerState_t *ps; cent = &cg_entities[cg.snap->ps.clientNum]; ps = &cg.snap->ps; if ( cent->currentState.weapon ) { value = ps->ammo[cent->currentState.weapon]; if ( value > -1 ) { if (shader) { trap->R_SetColor( color ); CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader); trap->R_SetColor( NULL ); } else { Com_sprintf (num, sizeof(num), "%i", value); width = CG_Text_Width(num, scale, 0); CG_Text_Paint(rect->x + (rect->w - width) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle); } } } }
static void CG_DrawKiller(rectDef_t *rect, float scale, vector4 *color, qhandle_t shader, int textStyle ) { // fragged by ... line if ( cg.killerName[0] ) { float x = rect->x + rect->w / 2; CG_Text_Paint(x - CG_Text_Width(CG_GetKillerText(), scale, 0) / 2, rect->y + rect->h, scale, color, CG_GetKillerText(), 0, 0, textStyle); } }
static void CG_DrawRedFlagName(rectDef_t *rect, float scale, vector4 *color, int textStyle ) { int i; for ( i = 0 ; i < cgs.maxclients ; i++ ) { if ( cgs.clientinfo[i].infoValid && cgs.clientinfo[i].team == TEAM_BLUE && cgs.clientinfo[i].powerups & ( 1<< PW_REDFLAG )) { CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, cgs.clientinfo[i].name, 0, 0, textStyle); return; } } }
static void CG_DrawPlayerLocation( rectDef_t *rect, float scale, vector4 *color, int textStyle ) { clientInfo_t *ci = &cgs.clientinfo[cg.snap->ps.clientNum]; if (ci) { const char *p = CG_ConfigString(CS_LOCATIONS + ci->location); if (!p || !*p) { p = "unknown"; } CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, p, 0, 0, textStyle); } }
static int JPLua_Export_DrawText( lua_State *L ) { vector4 colour = { 1.0f }; JPLua_ReadFloats( colour.raw, 4, L, 4 ); CG_Text_Paint( (float)lua_tonumber( L, 1 ), (float)lua_tonumber( L, 2 ), (float)lua_tonumber( L, 5 ), &colour, lua_tostring( L, 3 ), 0.0f, 0, lua_tointeger( L, 6 ), lua_tointeger( L, 7 ) ); return 0; }
/* =================== CG_DrawItemSelectText =================== */ void CG_DrawItemSelectText( rectDef_t *rect, float scale, int textStyle ) { int x, w; char *name; float *color; color = CG_FadeColor( cg.weaponSelectTime, WEAPON_SELECT_TIME ); if( !color ) return; trap_R_SetColor( color ); // draw the selected name if( cg.weaponSelect <= 32 ) { if( cg_weapons[ cg.weaponSelect ].registered && BG_InventoryContainsWeapon( cg.weaponSelect, cg.snap->ps.stats ) ) { if( ( name = cg_weapons[ cg.weaponSelect ].humanName ) ) { w = CG_Text_Width( name, scale, 0 ); x = rect->x + rect->w / 2; CG_Text_Paint( x - w / 2, rect->y + rect->h, scale, color, name, 0, 0, textStyle ); } } } else if( cg.weaponSelect > 32 ) { if( cg_upgrades[ cg.weaponSelect - 32 ].registered && BG_InventoryContainsUpgrade( cg.weaponSelect - 32, cg.snap->ps.stats ) ) { if( ( name = cg_upgrades[ cg.weaponSelect - 32 ].humanName ) ) { w = CG_Text_Width( name, scale, 0 ); x = rect->x + rect->w / 2; CG_Text_Paint( x - w / 2, rect->y + rect->h, scale, color, name, 0, 0, textStyle ); } } } trap_R_SetColor( NULL ); }
static void CG_DrawBlueScore(rectDef_t *rect, float scale, vector4 *color, qhandle_t shader, int textStyle ) { char num[16]; float width; if ( cgs.scores2 == SCORE_NOT_PRESENT ) Com_sprintf (num, sizeof(num), "-"); else Com_sprintf (num, sizeof(num), "%i", cgs.scores2); width = CG_Text_Width(num, scale, 0); CG_Text_Paint(rect->x + rect->w - width, rect->y + rect->h, scale, color, num, 0, 0, textStyle); }
static void CG_DrawPingInfo( rectDef_t *rect, float scale, vector4 *color, qhandle_t shader, int textStyle ) { vector4 pingColour = { 1.0f, 1.0f, 1.0f, 1.0f }, pingGood = { 0.0f, 1.0f, 0.0f, 1.0f }, pingBad = { 1.0f, 0.0f, 0.0f, 1.0f }; float point = MIN( cg.snap->ping / BAD_PING, 1.0f ); if ( !cg_drawPing->boolean && !cg_debugHUD->boolean ) return; VectorLerp4( &pingGood, point, &pingBad, &pingColour ); pingColour.a = 1.0f; CG_Text_Paint( rect->x, rect->y, scale, &pingColour, va( "%i ping", cg.snap->ping ), 0, 0, textStyle ); }
static void CG_Text_PaintWithCursor (float x, float y, float scale, const vec4_t color, const char *text, int cursorPos, char cursor, int limit, int style, int fontIndex) { const fontInfo_t *font; if (fontIndex <= 0) { font = &cgDC.Assets.textFont; } else { font = &cgDC.Assets.extraFonts[fontIndex]; } CG_Text_Paint(x, y, scale, color, text, 0, limit, style, font); Com_Printf("FIXME cursor (%s)\n", text); //FIXME cursor }
static void CG_DrawPlayerScore( rectDef_t *rect, float scale, vector4 *color, qhandle_t shader, int textStyle ) { char num[16]; int value = cg.snap->ps.persistent[PERS_SCORE]; float width; if (shader) { trap->R_SetColor( color ); CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader); trap->R_SetColor( NULL ); } else { Com_sprintf (num, sizeof(num), "%i", value); width = CG_Text_Width(num, scale, 0); CG_Text_Paint(rect->x + (rect->w - width) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle); } }
void JP_ChatboxDraw( void ) { int i = MAX_CHATBOX_ENTRIES-min( cg_chatboxLineCount.integer, currentChatbox->numActiveLines ); int numLines = 0; int done = 0; chatEntry_t *last = NULL; if ( cg.scoreBoardShowing && !(cg.snap && cg.snap->ps.pm_type == PM_INTERMISSION) ) return; //i is the ideal index. Now offset for scrolling i += currentChatbox->scrollAmount; #if defined(_WIN32) && !defined(OPENJK) #if 0 if ( (trap->Key_GetCatcher() & KEYCATCH_MESSAGE) ) { int overStrike = *(int *)0x8859E0; int cls_realtime = *(int *)0x8AF224; int chatTeam = *(int *)0x8868EC; int chatClient = *(int *)0x8868E8; char cursorChar = overStrike ? '|' : '_'; char message[256] = { 0 }; char name[36] = { 0 }; char tmp[256] = { 0 }; int cursorOffset = 0; if ( chatTeam ) { Q_strncpyz( message, "^5Say team", sizeof( message ) ); } else { if ( chatClient == -1 ) Q_strncpyz( message, "^2Say", sizeof( message ) ); else { Q_strncpyz( name, cgs.clientinfo[chatClient].name, sizeof( name ) ); Q_CleanStr( name ); Com_sprintf( message, sizeof( message ), "^6Tell (%s)", name ); } } cursorOffset = CG_Text_Width( va( "%s: ^7", message ), 64.0, JP_GetChatboxFont() ); CG_Text_Paint( cg_hudChatX.value, cg_hudChatY.value + (cg_chatLH.value*cg_chatLines.integer), cg_hudChatS.value, colorWhite, va( "%s: ^7%s", message, chatField->buffer ), 0.0f, 0, ITEM_TEXTSTYLE_OUTLINED, JP_GetChatboxFont() ); Q_strncpyz( tmp, chatField->buffer, min( sizeof( tmp ), chatField->cursor )+1 ); CG_Text_Paint( cg_hudChatX.value + (CG_Text_Width( tmp, 64.0, JP_GetChatboxFont() )*cg_hudChatS.value*0.015625) + (cursorOffset*cg_hudChatS.value*0.015625), cg_hudChatY.value + (cg_chatLH.value*cg_chatLines.integer), cg_hudChatS.value, colorWhite, va( "%c", ( (int)( cls_realtime >> 8 ) & 1 ) ? '\n' : cursorChar ), 0.0f, 0, ITEM_TEXTSTYLE_OUTLINED, JP_GetChatboxFont() ); }
void CG_DrawInformation( void ) { const char *s; const char *info; const char *sysInfo; //int y; //int value, valueNOFP; qhandle_t levelshot; //char buf[1024]; // int iPropHeight = 18; // I know, this is total crap, but as a post release asian-hack.... -Ste info = CG_ConfigString( CS_SERVERINFO ); sysInfo = CG_ConfigString( CS_SYSTEMINFO ); s = Info_ValueForKey( info, "mapname" ); levelshot = trap->R_RegisterShaderNoMip( va( "levelshots/%s", s ) ); if ( !levelshot ) { levelshot = trap->R_RegisterShaderNoMip( "menu/art/unknownmap_mp" ); } trap->R_SetColor( NULL ); CG_DrawPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, levelshot ); CG_LoadBar(); // the first 150 rows are reserved for the client connection // screen to write into if ( cg.infoScreenText[0] ) { const char *psLoading = CG_GetStringEdString("MENUS", "LOADING_MAPNAME"); UI_DrawProportionalString( 425, 105, ( const char * ) va(( char * ) /*"Loading... %s"*/ psLoading, cg.infoScreenText), UI_RIGHT|UI_BIGFONT|UI_DROPSHADOW, colorWhite, FONT_SMALL3 ); } else { const char *psAwaitingSnapshot = CG_GetStringEdString("MENUS", "AWAITING_SNAPSHOT"); UI_DrawProportionalString( 425, 128-32, ( const char * ) /*"Awaiting snapshot..."*/psAwaitingSnapshot, UI_RIGHT|UI_INFOFONT|UI_DROPSHADOW, colorWhite, FONT_SMALL3 ); } // Draw the loading screen tip if (cg_loadingTips.size() > 0 && cg_displayTipNumber != -1) { const char* loadingTip = CG_GetStringEdString2(cg_loadingTips.at(cg_displayTipNumber).tipText); int x = 320 - CG_Text_Width(loadingTip, 0.3f, FONT_SMALL) / 2; int y = 440; CG_Text_Paint(x, y, 0.3, colorWhite, loadingTip, 0, 0, ITEM_TEXTSTYLE_SHADOWED, FONT_SMALL); } }
void UI_DrawProportionalString( int x, int y, const char* str, int style, vec4_t color ) { // having all these different style defines (1 for UI, one for CG, and now one for the re->font stuff) // is dumb, but for now... // int iStyle = 0; int iMenuFont = (style & UI_SMALLFONT) ? FONT_SMALL : FONT_MEDIUM; switch (style & (UI_LEFT|UI_CENTER|UI_RIGHT)) { default: case UI_LEFT: { // nada... } break; case UI_CENTER: { x -= CG_Text_Width(str, 1.0, iMenuFont) / 2; } break; case UI_RIGHT: { x -= CG_Text_Width(str, 1.0, iMenuFont) / 2; } break; } if (style & UI_DROPSHADOW) { iStyle = ITEM_TEXTSTYLE_SHADOWED; } else if ( style & (UI_BLINK|UI_PULSE) ) { iStyle = ITEM_TEXTSTYLE_BLINK; } CG_Text_Paint(x, y, 1.0, color, str, 0, 0, iStyle, iMenuFont); }
static void CG_DrawPlayerArmorValue(rectDef_t *rect, float scale, vector4 *color, qhandle_t shader, int textStyle) { char num[16]; int value; float width; playerState_t *ps; ps = &cg.snap->ps; value = ps->stats[STAT_ARMOR]; if (shader) { trap->R_SetColor( color ); CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader); trap->R_SetColor( NULL ); } else { Com_sprintf (num, sizeof(num), "%i", value); width = CG_Text_Width(num, scale, 0); CG_Text_Paint(rect->x + (rect->w - width) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle); } }
static void DrawSpectators( float fade ) { const qhandle_t fontHandle = MenuFontToHandle( JP_GetScoreboardFont() ); const float fontScale = 0.5f, lineHeight = 14.0f; float y = 128.0f; vector4 white = { 1.0f, 1.0f, 1.0f, 1.0f }; white.a = fade; CG_BuildSpectatorString(); cg.scoreboard.spectatorWidth = CG_Text_Width( cg.scoreboard.spectatorList, fontScale, fontHandle ); if ( cg.scoreboard.spectatorLen ) { const float dt = (cg.time - cg.scoreboard.spectatorResetTime)*0.0625f; cg.scoreboard.spectatorX = SCREEN_WIDTH - (1.0f)*dt; if ( cg.scoreboard.spectatorX < 0 - cg.scoreboard.spectatorWidth ) { cg.scoreboard.spectatorX = SCREEN_WIDTH; cg.scoreboard.spectatorResetTime = cg.time; } CG_Text_Paint( cg.scoreboard.spectatorX, (y + lineHeight * 20) - 3, fontScale, &white, cg.scoreboard.spectatorList, 0, 0, ITEM_TEXTSTYLE_SHADOWED, fontHandle ); } }
static void CG_DrawTimer( rectDef_t *rect, float scale, vector4 *color, qhandle_t shader, int textStyle ) { const vector4 *timeColour = NULL; int msec=0, secs=0, mins=0, limitSec=cgs.timelimit*60; if ( !cg_drawTimer->boolean && !cg_debugHUD->boolean && !cg.intermissionStarted ) return; msec = cg.time-cgs.levelStartTime; secs = msec/1000; mins = secs/60; timeColour = &g_color_table[ColorIndex(COLOR_WHITE)]; if ( cgs.timelimit ) { // final minute if ( secs >= limitSec-60 ) timeColour = &g_color_table[ColorIndex(COLOR_RED)]; // last quarter else if ( secs >= limitSec-(limitSec/4) ) timeColour = &g_color_table[ColorIndex(COLOR_ORANGE)]; // half way else if ( secs >= limitSec/2 ) timeColour = &g_color_table[ColorIndex(COLOR_YELLOW)]; } if ( cgs.timelimit && cg_drawTimer->integer == 2 ) {// count down msec = limitSec*1000 - (msec); secs = msec/1000; mins = secs/60; } secs %= 60; msec %= 1000; //QTZTODO: Masked timer? CG_Text_Paint( rect->x, rect->y, scale, (vector4*)timeColour, va( "%i:%02i", mins, secs ), 0, 0, textStyle ); }
static void CG_DrawBlueName(rectDef_t *rect, float scale, vector4 *color, int textStyle ) { CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, cgs.blueTeam, 0, 0, textStyle); }
static void CG_DrawGameStatus(rectDef_t *rect, float scale, vector4 *color, qhandle_t shader, int textStyle ) { CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, CG_GetGameStatusText(), 0, 0, textStyle); }
/* ================= CG_DrawScoreboard ================= */ static void CG_DrawClientScore( int y, score_t *score, float *color, float fade, qboolean largeFormat ) { //vec3_t headAngles; clientInfo_t *ci; int iconx, headx; float scale; if ( largeFormat ) { scale = 1.0f; } else { scale = 0.75f; } if ( score->client < 0 || score->client >= cgs.maxclients ) { Com_Printf( "Bad score->client: %i\n", score->client ); return; } ci = &cgs.clientinfo[score->client]; iconx = SB_BOTICON_X + (SB_RATING_WIDTH / 2); headx = SB_HEAD_X + (SB_RATING_WIDTH / 2); // draw the handicap or bot skill marker (unless player has flag) if ( ci->powerups & ( 1 << PW_NEUTRALFLAG ) ) { if( largeFormat ) { CG_DrawFlagModel( iconx, y - ( 32 - BIGCHAR_HEIGHT ) / 2, 32, 32, TEAM_FREE, qfalse ); } else { CG_DrawFlagModel( iconx, y, 16, 16, TEAM_FREE, qfalse ); } } else if ( ci->powerups & ( 1 << PW_REDFLAG ) ) { if( largeFormat ) { CG_DrawFlagModel( iconx*cgs.screenXScale, y*cgs.screenYScale, 32*cgs.screenXScale, 32*cgs.screenYScale, TEAM_RED, qfalse ); } else { CG_DrawFlagModel( iconx*cgs.screenXScale, y*cgs.screenYScale, 32*cgs.screenXScale, 32*cgs.screenYScale, TEAM_RED, qfalse ); } } else if ( ci->powerups & ( 1 << PW_BLUEFLAG ) ) { if( largeFormat ) { CG_DrawFlagModel( iconx*cgs.screenXScale, y*cgs.screenYScale, 32*cgs.screenXScale, 32*cgs.screenYScale, TEAM_BLUE, qfalse ); } else { CG_DrawFlagModel( iconx*cgs.screenXScale, y*cgs.screenYScale, 32*cgs.screenXScale, 32*cgs.screenYScale, TEAM_BLUE, qfalse ); } } else { // draw the wins / losses /* if ( cgs.gametype == GT_TOURNAMENT ) { CG_DrawSmallStringColor( iconx, y + SMALLCHAR_HEIGHT/2, va("%i/%i", ci->wins, ci->losses ), color ); } */ //rww - in duel, we now show wins/losses in place of "frags". This is because duel now defaults to 1 kill per round. } // highlight your position if ( score->client == cg.snap->ps.clientNum ) { float hcolor[4]; int rank; localClient = qtrue; if ( cg.snap->ps.persistant[PERS_TEAM] == TEAM_SPECTATOR || GT_Team(cgs.gametype) ) { rank = -1; } else { rank = cg.snap->ps.persistant[PERS_RANK] & ~RANK_TIED_FLAG; } if ( rank == 0 ) { hcolor[0] = 0; hcolor[1] = 0; hcolor[2] = 0.7f; } else if ( rank == 1 ) { hcolor[0] = 0.7f; hcolor[1] = 0; hcolor[2] = 0; } else if ( rank == 2 ) { hcolor[0] = 0.7f; hcolor[1] = 0.7f; hcolor[2] = 0; } else { hcolor[0] = 0.7f; hcolor[1] = 0.7f; hcolor[2] = 0.7f; } hcolor[3] = fade * 0.7; CG_FillRect( SB_SCORELINE_X - 5, y + 2, 640 - SB_SCORELINE_X * 2 + 10, largeFormat?SB_NORMAL_HEIGHT:SB_INTER_HEIGHT, hcolor ); } CG_Text_Paint (SB_NAME_X, y, 0.9f * scale, colorWhite, ci->name,0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); if ( ci->team != TEAM_SPECTATOR || cgs.gametype == GT_TOURNAMENT ) { if (cgs.gametype == GT_TOURNAMENT) { CG_Text_Paint (SB_SCORE_X, y, 1.0f * scale, colorWhite, va("%i/%i", ci->wins, ci->losses),0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_SMALL ); } else { CG_Text_Paint (SB_SCORE_X, y, 1.0f * scale, colorWhite, va("%i", score->score),0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_SMALL ); } } CG_Text_Paint (SB_PING_X, y, 1.0f * scale, colorWhite, va("%i", score->ping),0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_SMALL ); CG_Text_Paint (SB_TIME_X, y, 1.0f * scale, colorWhite, va("%i", score->time),0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_SMALL ); // add the "ready" marker for intermission exiting if ( cg.snap->ps.stats[ STAT_CLIENTS_READY ] & ( 1 << score->client ) ) { CG_Text_Paint (SB_NAME_X - 64, y + 2, 0.7f * scale, colorWhite, CG_GetStripEdString("INGAMETEXT", "READY"),0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); } }
static void CG_DrawAreaPowerUp(rectDef_t *rect, int align, float special, float scale, vector4 *color) { char num[16]; int sorted[MAX_POWERUPS], sortedTime[MAX_POWERUPS]; int i, j, k, t, active; float f, *inc; playerState_t *ps; const gitem_t *item; rectDef_t r2; r2.x = rect->x; r2.y = rect->y; r2.w = rect->w; r2.h = rect->h; inc = (align == HUD_VERTICAL) ? &r2.y : &r2.x; ps = &cg.snap->ps; if ( ps->stats[STAT_HEALTH] <= 0 ) { return; } // sort the list by time remaining active = 0; for ( i = 0 ; i < MAX_POWERUPS ; i++ ) { if ( !ps->powerups[ i ] ) { continue; } t = ps->powerups[ i ] - cg.time; // ZOID--don't draw if the power up has unlimited time (999 seconds) // This is true of the CTF flags if ( t <= 0 || t >= 999000) { continue; } // insert into the list for ( j = 0 ; j < active ; j++ ) { if ( sortedTime[j] >= t ) { for ( k = active - 1 ; k >= j ; k-- ) { sorted[k+1] = sorted[k]; sortedTime[k+1] = sortedTime[k]; } break; } } sorted[j] = i; sortedTime[j] = t; active++; } // draw the icons and timers for ( i = 0 ; i < active ; i++ ) { item = BG_FindItemForPowerup( sorted[i] ); if (item) { t = ps->powerups[ sorted[i] ]; if ( t - cg.time >= POWERUP_BLINKS * POWERUP_BLINK_TIME ) { trap->R_SetColor( NULL ); } else { vector4 modulate; f = (float)( t - cg.time ) / POWERUP_BLINK_TIME; f -= (int)f; modulate.r = modulate.g = modulate.b = modulate.a = f; trap->R_SetColor( &modulate ); } CG_DrawPic( r2.x, r2.y, r2.w * .75f, r2.h, trap->R_RegisterShader( item->icon ) ); Com_sprintf (num, sizeof(num), "%i", sortedTime[i] / 1000); CG_Text_Paint(r2.x + (r2.w * .75f) + 3 , r2.y + r2.h, scale, color, num, 0, 0, 0); *inc += r2.w + special; } } trap->R_SetColor( NULL ); }
/* ================= CG_DrawScoreboard Draw the normal in-game scoreboard ================= */ qboolean CG_DrawOldScoreboard( void ) { int x, y, w, i, n1, n2; float fade; float *fadeColor; char *s; int maxClients; int lineHeight; int topBorderSize, bottomBorderSize; // don't draw amuthing if the menu or console is up if ( cg_paused.integer ) { cg.deferredPlayerLoading = 0; return qfalse; } // don't draw scoreboard during death while warmup up if ( cg.warmup && !cg.showScores ) { return qfalse; } if ( cg.showScores || cg.predictedPlayerState.pm_type == PM_DEAD || cg.predictedPlayerState.pm_type == PM_INTERMISSION ) { fade = 1.0; fadeColor = colorWhite; } else { fadeColor = CG_FadeColor( cg.scoreFadeTime, FADE_TIME ); if ( !fadeColor ) { // next time scoreboard comes up, don't print killer cg.deferredPlayerLoading = 0; cg.killerName[0] = 0; return qfalse; } fade = *fadeColor; } // fragged by ... line // or if in intermission and duel, prints the winner of the duel round if (cgs.gametype == GT_TOURNAMENT && cgs.duelWinner != -1 && cg.predictedPlayerState.pm_type == PM_INTERMISSION) { s = va("%s %s", cgs.clientinfo[cgs.duelWinner].name, CG_GetStripEdString("INGAMETEXT", "DUEL_WINS") ); /*w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; x = ( SCREEN_WIDTH - w ) / 2; y = 40; CG_DrawBigString( x, y, s, fade ); */ x = ( SCREEN_WIDTH ) / 2; y = 40; CG_Text_Paint ( x - CG_Text_Width ( s, 1.0f, FONT_MEDIUM ) / 2, y, 1.0f, colorWhite, s, 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); } else if (cgs.gametype == GT_TOURNAMENT && cgs.duelist1 != -1 && cgs.duelist2 != -1 && cg.predictedPlayerState.pm_type == PM_INTERMISSION) { s = va("%s %s %s", cgs.clientinfo[cgs.duelist1].name, CG_GetStripEdString("INGAMETEXT", "SPECHUD_VERSUS"), cgs.clientinfo[cgs.duelist2].name ); /*w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; x = ( SCREEN_WIDTH - w ) / 2; y = 40; CG_DrawBigString( x, y, s, fade ); */ x = ( SCREEN_WIDTH ) / 2; y = 40; CG_Text_Paint ( x - CG_Text_Width ( s, 1.0f, FONT_MEDIUM ) / 2, y, 1.0f, colorWhite, s, 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); } else if ( cg.killerName[0] ) { s = va("%s %s", CG_GetStripEdString("INGAMETEXT", "KILLEDBY"), cg.killerName ); /*w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; x = ( SCREEN_WIDTH - w ) / 2; y = 40; CG_DrawBigString( x, y, s, fade ); */ x = ( SCREEN_WIDTH ) / 2; y = 40; CG_Text_Paint ( x - CG_Text_Width ( s, 1.0f, FONT_MEDIUM ) / 2, y, 1.0f, colorWhite, s, 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); } // current rank if ( !GT_Team(cgs.gametype)) { if (cg.snap->ps.persistant[PERS_TEAM] != TEAM_SPECTATOR ) { char sPlace[256]; char sOf[256]; char sWith[256]; trap_SP_GetStringTextString("INGAMETEXT_PLACE", sPlace, sizeof(sPlace)); trap_SP_GetStringTextString("INGAMETEXT_OF", sOf, sizeof(sOf)); trap_SP_GetStringTextString("INGAMETEXT_WITH", sWith, sizeof(sWith)); s = va("%s %s (%s %i) %s %i", CG_PlaceString( cg.snap->ps.persistant[PERS_RANK] + 1 ), sPlace, sOf, cg.numScores, sWith, cg.snap->ps.persistant[PERS_SCORE] ); w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; x = ( SCREEN_WIDTH ) / 2; y = 60; //CG_DrawBigString( x, y, s, fade ); UI_DrawProportionalString(x, y, s, UI_CENTER|UI_DROPSHADOW, colorTable[CT_WHITE]); } } else { if ( cg.teamScores[0] == cg.teamScores[1] ) { s = va("Teams are tied at %i", cg.teamScores[0] ); } else if ( cg.teamScores[0] >= cg.teamScores[1] ) { s = va("Red leads %i to %i",cg.teamScores[0], cg.teamScores[1] ); } else { s = va("Blue leads %i to %i",cg.teamScores[1], cg.teamScores[0] ); } x = ( SCREEN_WIDTH ) / 2; y = 60; CG_Text_Paint ( x - CG_Text_Width ( s, 1.0f, FONT_MEDIUM ) / 2, y, 1.0f, colorWhite, s, 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); } // scoreboard y = SB_HEADER; CG_DrawPic ( SB_SCORELINE_X - 40, y - 5, SB_SCORELINE_WIDTH + 80, 40, trap_R_RegisterShaderNoMip ( "gfx/menus/menu_buttonback.tga" ) ); // "NAME", "SCORE", "PING", "TIME" weren't localised, GODDAMMIT!!!!!!!! // // Unfortunately, since it's so sodding late now and post release I can't enable the localisation code (REM'd) since some of // the localised strings don't fit - since no-one's ever seen them to notice this. Smegging brilliant. Thanks people. // CG_Text_Paint ( SB_NAME_X, y, 1.0f, colorWhite, /*CG_GetStripEdString("MENUS3", "NAME")*/"Name",0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); if (cgs.gametype == GT_TOURNAMENT) { char sWL[100]; trap_SP_GetStringTextString("INGAMETEXT_W_L", sWL, sizeof(sWL)); CG_Text_Paint ( SB_SCORE_X, y, 1.0f, colorWhite, sWL, 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); } else { CG_Text_Paint ( SB_SCORE_X, y, 1.0f, colorWhite, /*CG_GetStripEdString("MENUS3", "SCORE")*/"Score", 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); } CG_Text_Paint ( SB_PING_X, y, 1.0f, colorWhite, /*CG_GetStripEdString("MENUS0", "PING")*/"Ping", 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); CG_Text_Paint ( SB_TIME_X, y, 1.0f, colorWhite, /*CG_GetStripEdString("MENUS3", "TIME")*/"Time", 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); y = SB_TOP; // If there are more than SB_MAXCLIENTS_NORMAL, use the interleaved scores if ( cg.numScores > SB_MAXCLIENTS_NORMAL ) { maxClients = SB_MAXCLIENTS_INTER; lineHeight = SB_INTER_HEIGHT; topBorderSize = 8; bottomBorderSize = 16; } else { maxClients = SB_MAXCLIENTS_NORMAL; lineHeight = SB_NORMAL_HEIGHT; topBorderSize = 8; bottomBorderSize = 8; } localClient = qfalse; //I guess this should end up being able to display 19 clients at once. //In a team game, if there are 9 or more clients on the team not in the lead, //we only want to show 10 of the clients on the team in the lead, so that we //have room to display the clients in the lead on the losing team. //I guess this can be accomplished simply by printing the first teams score with a maxClients //value passed in related to how many players are on both teams. if ( GT_Team(cgs.gametype) ) { // // teamplay scoreboard // y += lineHeight/2; if ( cg.teamScores[0] >= cg.teamScores[1] ) { int team1MaxCl = CG_GetTeamCount(TEAM_RED, maxClients); int team2MaxCl = CG_GetTeamCount(TEAM_BLUE, maxClients); if (team1MaxCl > 10 && (team1MaxCl+team2MaxCl) > maxClients) { team1MaxCl -= team2MaxCl; //subtract as many as you have to down to 10, once we get there //we just set it to 10 if (team1MaxCl < 10) { team1MaxCl = 10; } } team2MaxCl = (maxClients-team1MaxCl); //team2 can display however many is left over after team1's display n1 = CG_TeamScoreboard( y, TEAM_RED, fade, team1MaxCl, lineHeight, qtrue ); CG_DrawTeamBackground( SB_SCORELINE_X - 5, y - topBorderSize, 640 - SB_SCORELINE_X * 2 + 10, n1 * lineHeight + bottomBorderSize, 0.33f, TEAM_RED ); CG_TeamScoreboard( y, TEAM_RED, fade, team1MaxCl, lineHeight, qfalse ); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; //maxClients -= n1; n2 = CG_TeamScoreboard( y, TEAM_BLUE, fade, team2MaxCl, lineHeight, qtrue ); CG_DrawTeamBackground( SB_SCORELINE_X - 5, y - topBorderSize, 640 - SB_SCORELINE_X * 2 + 10, n2 * lineHeight + bottomBorderSize, 0.33f, TEAM_BLUE ); CG_TeamScoreboard( y, TEAM_BLUE, fade, team2MaxCl, lineHeight, qfalse ); y += (n2 * lineHeight) + BIGCHAR_HEIGHT; //maxClients -= n2; maxClients -= (team1MaxCl+team2MaxCl); } else { int team1MaxCl = CG_GetTeamCount(TEAM_BLUE, maxClients); int team2MaxCl = CG_GetTeamCount(TEAM_RED, maxClients); if (team1MaxCl > 10 && (team1MaxCl+team2MaxCl) > maxClients) { team1MaxCl -= team2MaxCl; //subtract as many as you have to down to 10, once we get there //we just set it to 10 if (team1MaxCl < 10) { team1MaxCl = 10; } } team2MaxCl = (maxClients-team1MaxCl); //team2 can display however many is left over after team1's display n1 = CG_TeamScoreboard( y, TEAM_BLUE, fade, team1MaxCl, lineHeight, qtrue ); CG_DrawTeamBackground( SB_SCORELINE_X - 5, y - topBorderSize, 640 - SB_SCORELINE_X * 2 + 10, n1 * lineHeight + bottomBorderSize, 0.33f, TEAM_BLUE ); CG_TeamScoreboard( y, TEAM_BLUE, fade, team1MaxCl, lineHeight, qfalse ); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; //maxClients -= n1; n2 = CG_TeamScoreboard( y, TEAM_RED, fade, team2MaxCl, lineHeight, qtrue ); CG_DrawTeamBackground( SB_SCORELINE_X - 5, y - topBorderSize, 640 - SB_SCORELINE_X * 2 + 10, n2 * lineHeight + bottomBorderSize, 0.33f, TEAM_RED ); CG_TeamScoreboard( y, TEAM_RED, fade, team2MaxCl, lineHeight, qfalse ); y += (n2 * lineHeight) + BIGCHAR_HEIGHT; //maxClients -= n2; maxClients -= (team1MaxCl+team2MaxCl); } n1 = CG_TeamScoreboard( y, TEAM_SPECTATOR, fade, maxClients, lineHeight, qfalse ); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; } else { // // free for all scoreboard // n1 = CG_TeamScoreboard( y, TEAM_FREE, fade, maxClients, lineHeight, qfalse ); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; n2 = CG_TeamScoreboard( y, TEAM_SPECTATOR, fade, maxClients - n1, lineHeight, qfalse ); y += (n2 * lineHeight) + BIGCHAR_HEIGHT; } if (!localClient) { // draw local client at the bottom for ( i = 0 ; i < cg.numScores ; i++ ) { if ( cg.scores[i].client == cg.snap->ps.clientNum ) { CG_DrawClientScore( y, &cg.scores[i], fadeColor, fade, lineHeight == SB_NORMAL_HEIGHT ); break; } } } // load any models that have been deferred if ( ++cg.deferredPlayerLoading > 10 ) { CG_LoadDeferredPlayers(); } return qtrue; }
void CG_DrawStringExt( int x, int y, const char *string, const float *setColor, qboolean forceColor, qboolean shadow, int charWidth, int charHeight, int maxChars, qhandle_t textShader ) { if (trap_Language_IsAsian()) { // hack-a-doodle-do (post-release quick fix code)... // vec4_t color; memcpy(color,setColor, sizeof(color)); // de-const it CG_Text_Paint(x, y, 1.0f, // float scale, color, // vec4_t color, string, // const char *text, 0.0f, // float adjust, 0, // int limit, shadow ? ITEM_TEXTSTYLE_SHADOWED : 0, // int style, FONT_MEDIUM // iMenuFont ) ; } else { vec4_t color; const char *s; int xx; int yy; // draw the drop shadow if (shadow) { color[0] = color[1] = color[2] = 0; color[3] = setColor[3]; trap_R_SetColor( color ); s = string; xx = x; yy = y; while ( *s ) { if(*s == '^') { //Don't include color codes if(*(s+1) >= '0' && *(s+1) <= '9') { s+=2; continue; } else if(*(s+1) == 'x' && Text_IsExtColorCode((s+1))) { s+=5; continue; } } else if(*s == '\n') { yy += charHeight; xx = x; s++; continue; } //trap_R_DrawStretchPic( xx + 2, yy+2, charWidth, charHeight, 8, 16, CG_DrawChar( xx + 2, yy + 2, charWidth, charHeight, *s, textShader ); xx += charWidth; s++; } } // draw the colored text s = string; xx = x; yy = y; trap_R_SetColor( setColor ); while ( *s ) { if(*s == '\n') { //Handle newlines yy += charHeight; xx = x; s++; continue; } else if(*s == '^') { //Handle color codes if(*(s+1) >= '0' && *(s+1) <= '9') { if(!forceColor) { memcpy( color, g_color_table[ColorIndex(*(s+1))], sizeof( color ) ); color[3] = setColor[3]; trap_R_SetColor( color ); } s+= 2; continue; } else if(*(s+1) == 'x') { if(strlen(s) > 5) { if(!forceColor) { int i; for(i=0; i<3; i++) { if((s+2+i)) { char letter = *(s+2+i); if(*(s+2+i) >= '0' && *(s+2+i) <= '9') { color[i] = (atof(va("%c", letter))/16.0f); } else if((*(s+2+i) >= 'A' && *(s+2+i) <= 'F') || (*(s+2+i) >= 'a' && *(s+2+i) <= 'f')) { char *endPtr = NULL; long value = strtol(va("0x%c", letter), &endPtr, 16); color[i] = (float)value/16.0f; } } } color[3] = setColor[3]; trap_R_SetColor( color ); } s += 5; continue; } } } CG_DrawChar( xx + 2, yy, charWidth, charHeight, *s, textShader ); xx += charWidth-1; s++; } trap_R_SetColor( NULL ); } }
static void CG_DrawCapFragLimit(rectDef_t *rect, float scale, vector4 *color, qhandle_t shader, int textStyle) { int limit = (cgs.gametype >= GT_FLAGS) ? cgs.capturelimit : cgs.fraglimit; CG_Text_Paint(rect->x, rect->y, scale, color, va("%2i", limit),0, 0, textStyle); }
static void CG_Draw2ndPlace(rectDef_t *rect, float scale, vector4 *color, qhandle_t shader, int textStyle) { if (cgs.scores2 != SCORE_NOT_PRESENT) { CG_Text_Paint(rect->x, rect->y, scale, color, va("%2i", cgs.scores2),0, 0, textStyle); } }
static void CG_DrawGameType(rectDef_t *rect, float scale, vector4 *color, qhandle_t shader, int textStyle ) { CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, GametypeStringForID( cgs.gametype ), 0, 0, textStyle); }