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 ); }
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() ); }
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); } } } }
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); }
int CG_TrimLeftPixels(char *instr, float scale, float w, int size) { char buffer[1024]; char *p, *s; int tw; int i; Q_strncpyz(buffer, instr, 1024); memset(instr, 0, size); for(i = 0, p = buffer; *p; p++, i++) { instr[i] = *p; tw = CG_Text_Width(instr, scale, 0); if(tw >= w) { memset(instr, 0, size); for(s = instr, p = &buffer[i + 1]; *p && ((s - instr) < size); p++, s++) { *s = *p; } return tw - w; } } return -1; }
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); } }
void CG_DrawTeamSpectators(rectDef_t *rect, float scale, vector4 *color, qhandle_t shader) { if (cg.spectatorLen) { float maxX; if (cg.spectatorWidth == -1) { cg.spectatorWidth = 0; cg.spectatorPaintX = rect->x + 1; cg.spectatorPaintX2 = -1; } if (cg.spectatorOffset > cg.spectatorLen) { cg.spectatorOffset = 0; cg.spectatorPaintX = rect->x + 1; cg.spectatorPaintX2 = -1; } if (cg.time > cg.spectatorTime) { cg.spectatorTime = cg.time + 10; if (cg.spectatorPaintX <= rect->x + 2) { if (cg.spectatorOffset < cg.spectatorLen) { cg.spectatorPaintX += CG_Text_Width(&cg.spectatorList[cg.spectatorOffset], scale, 1) - 1; cg.spectatorOffset++; } else { cg.spectatorOffset = 0; if (cg.spectatorPaintX2 >= 0) { cg.spectatorPaintX = cg.spectatorPaintX2; } else { cg.spectatorPaintX = rect->x + rect->w - 2; } cg.spectatorPaintX2 = -1; } } else { cg.spectatorPaintX--; if (cg.spectatorPaintX2 >= 0) { cg.spectatorPaintX2--; } } } maxX = rect->x + rect->w - 2; CG_Text_Paint_Limit(&maxX, (float)cg.spectatorPaintX, rect->y + rect->h - 3, scale, color, &cg.spectatorList[cg.spectatorOffset], 0, 0); if (cg.spectatorPaintX2 >= 0) { float maxX2 = rect->x + rect->w - 2; CG_Text_Paint_Limit(&maxX2, (float)cg.spectatorPaintX2, rect->y + rect->h - 3, scale, color, cg.spectatorList, 0, cg.spectatorOffset); } if (cg.spectatorOffset && maxX > 0) { // if we have an offset ( we are skipping the first part of the string ) and we fit the string if (cg.spectatorPaintX2 == -1) { cg.spectatorPaintX2 = rect->x + rect->w - 2; } } else { cg.spectatorPaintX2 = -1; } } }
void CG_FitTextToWidth2(char *instr, float scale, float w, int size) { char buffer[1024]; char *s, *p, *c, *ls; int l; Q_strncpyz(buffer, instr, 1024); memset(instr, 0, size); c = s = instr; p = buffer; ls = NULL; l = 0; while(*p) { *c = *p++; l++; if(*c == ' ') { ls = c; } // store last space, to try not to break mid word c++; if(*p == '\n') { s = c + 1; l = 0; } else if(CG_Text_Width(s, scale, 0) > w) { if(ls) { *ls = '\n'; s = ls + 1; } else { *c = *(c - 1); *(c - 1) = '\n'; s = c++; } ls = NULL; l = 0; } } if(c != buffer && (*(c - 1) != '\n')) { *c++ = '\n'; } *c = '\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 ); }
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_Text_Paint_Limit(float *maxX, float x, float y, float scale, vector4 *color, const char* text, float adjust, int limit) { size_t len, count; vector4 newColor; glyphInfo_t *glyph; if (text) { const char *s = text; float max = *maxX; float useScale; fontInfo_t *font = &cgDC.Assets.textFont; if (scale <= ui_smallFont->value) { font = &cgDC.Assets.smallFont; } else if (scale > ui_bigFont->value) { font = &cgDC.Assets.bigFont; } useScale = scale * font->glyphScale; trap->R_SetColor( color ); len = strlen(text); if (limit > 0 && len > limit) { len = limit; } count = 0; while (s && *s && count < len) { glyph = &font->glyphs[(int)*s]; // TTimo: FIXME: getting nasty warnings without the cast, hopefully this doesn't break the VM build if ( Q_IsColorString( s ) ) { memcpy( &newColor, &g_color_table[ColorIndex(*(s+1))], sizeof( newColor ) ); newColor.a = color->a; trap->R_SetColor( &newColor ); s += 2; continue; } else { float yadj = useScale * glyph->top; if (CG_Text_Width(s, useScale, 1) + x > max) { *maxX = 0; break; } CG_Text_PaintChar(x, y - yadj, (float)glyph->imageWidth, (float)glyph->imageHeight, useScale, glyph->s, glyph->t, glyph->s2, glyph->t2, glyph->glyph); x += (glyph->xSkip * useScale) + adjust; *maxX = x; count++; s++; } } 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 int JPLua_Export_Font_StringLengthPixels( lua_State *L ) { const char *text = lua_tostring(L, 1); float scale = lua_tonumber(L, 2); qhandle_t font = lua_tointeger(L, 3); qboolean customfont = lua_toboolean(L, 4); if (customfont) trap->R_Font_StrLenPixels(text, font, scale); else lua_pushnumber(L, CG_Text_Width(text, scale, font)); return 1; }
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 CG_FitTextToWidth_SingleLine( char* instr, float scale, float w, int size) { char *s, *p; char buffer[1024]; Q_strncpyz(buffer, instr, 1024); memset(instr, 0, size); p = instr; for( s = buffer; *s; s++, p++ ) { *p = *s; if(CG_Text_Width( instr, scale, 0 ) > w) { *p = '\0'; return; } } }
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); } }
static void DrawChatboxTabs( void ) { chatBox_t *cb = chatboxList; float xOffset = 0.0f; int cls_realtime = *(int *)0x8AF224; while ( cb ) { char *name = cb->shortname; float textWidth = CG_Text_Width( name, cg.chatbox.size.scale, JP_GetChatboxFont() ); float textHeight = CG_Text_Height( name, cg.chatbox.size.scale, JP_GetChatboxFont() ); CG_FillRect( cg.chatbox.pos.x + xOffset, cg.chatbox.pos.y + (cg_chatboxLineHeight.value*cg_chatboxLineCount.integer) + (textHeight*0.25f), textWidth+16.0f, cg_chatboxLineHeight.value, (cb==currentChatbox) ? &colorTable[CT_DKGREY] : &colorTable[CT_BLACK] ); CG_Text_Paint( cg.chatbox.pos.x + xOffset+8.0f, cg.chatbox.pos.y + (cg_chatboxLineHeight.value*cg_chatboxLineCount.integer), cg.chatbox.size.scale, &colorWhite, va( "^%c%s", (cb==currentChatbox) ? '2' : (cb->notification && ( (int)( cls_realtime >> 8 ) & 1 ) ) ? '1' : '7', cb->shortname ), 0.0f, 0, ITEM_TEXTSTYLE_OUTLINED, JP_GetChatboxFont() ); xOffset += textWidth + 16.0f; cb = cb->next; } }
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 float CG_OwnerDrawWidth (int ownerDraw, float scale, int fontIndex) { const fontInfo_t *font; const char *s; if (fontIndex <= 0) { font = &cgDC.Assets.textFont; } else { font = &cgDC.Assets.extraFonts[fontIndex]; } switch (ownerDraw) { case CG_GAME_TYPE: return CG_Text_Width(CG_GameTypeString(), scale, 0, font); case CG_GAME_STATUS: return CG_Text_Width(CG_GetGameStatusText(), scale, 0, font); break; case CG_KILLER: return CG_Text_Width(CG_GetKillerText(), scale, 0, font); break; case CG_RED_NAME: //return CG_Text_Width(cg_redTeamName.string, scale, 0, font); return CG_Text_Width(cgs.redTeamName, scale, 0, font); break; case CG_BLUE_NAME: //return CG_Text_Width(cg_blueTeamName.string, scale, 0, font); return CG_Text_Width(cgs.blueTeamName, scale, 0, font); break; case UI_KEYBINDSTATUS: if (Display_KeyBindPending()) { s = "Waiting for new key... Press ESCAPE to cancel"; } else { s = "Press ENTER or CLICK to change, Press BACKSPACE to clear"; } return CG_Text_Width(s, scale, 0, font); break; default: Com_Printf("CG_OwnerDrawWidth() unknown ownerDraw %d\n", ownerDraw); break; } return 0; }
static int JPLua_Export_Font_StringLengthPixels( lua_State *L ) { lua_pushnumber( L, CG_Text_Width( lua_tostring( L, 1 ), (float)lua_tonumber( L, 2 ), lua_tointeger( L, 3 ) ) ); return 1; }
/* ================= 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; }
qboolean CG_DrawOldScoreboard( void ) { int x, y, i, n1, n2; float fade; vector4 *fadeColor; char *s; int maxClients, realMaxClients; int lineHeight; int topBorderSize, bottomBorderSize; #if 0 // don't draw amuthing if the menu or console is up if ( cg_paused.integer ) { cg.deferredPlayerLoading = 0; return qfalse; } #endif // 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->a; } // fragged by ... line // or if in intermission and duel, prints the winner of the duel round if ((cgs.gametype == GT_DUEL || cgs.gametype == GT_POWERDUEL) && cgs.duelWinner != -1 && cg.predictedPlayerState.pm_type == PM_INTERMISSION) { s = va("%s^7 %s", cgs.clientinfo[cgs.duelWinner].name, CG_GetStringEdString("MP_INGAME", "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_DUEL || cgs.gametype == GT_POWERDUEL) && cgs.duelist1 != -1 && cgs.duelist2 != -1 && cg.predictedPlayerState.pm_type == PM_INTERMISSION) { if (cgs.gametype == GT_POWERDUEL && cgs.duelist3 != -1) { s = va("%s^7 %s %s^7 %s %s", cgs.clientinfo[cgs.duelist1].name, CG_GetStringEdString("MP_INGAME", "SPECHUD_VERSUS"), cgs.clientinfo[cgs.duelist2].name, CG_GetStringEdString("MP_INGAME", "AND"), cgs.clientinfo[cgs.duelist3].name ); } else { s = va("%s^7 %s %s", cgs.clientinfo[cgs.duelist1].name, CG_GetStringEdString("MP_INGAME", "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_GetStringEdString("MP_INGAME", "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 = 32; 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 { x = ( SCREEN_WIDTH ) / 2; y = SB_HEADER; //CG_DrawBigString( x, y, s, fade ); s = cgs.japp.serverName; CG_Text_Paint( x-(CG_Text_Width( s, 0.75f, FONT_NONE )/2), y, 0.75f, &colorTable[CT_WHITE], s, 0.0f, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_NONE ); if ( cgs.gametype >= GT_TEAM ) { int redCount=0, blueCount=0, specCount=0; for ( i=0; i<cg.numScores; i++ ) { if ( cgs.clientinfo[cg.scores[i].client].team == TEAM_RED ) redCount++; else if ( cgs.clientinfo[cg.scores[i].client].team == TEAM_BLUE ) blueCount++; else if ( cgs.clientinfo[cg.scores[i].client].team == TEAM_SPECTATOR ) specCount++; } s = va( "Players: ^2%i^7/^2%i ^7(^1%i^7/^5%i^7) - %i spectators", cg.numScores, cgs.maxclients, redCount, blueCount, specCount ); } else { int specCount=0; for ( i=0; i<cg.numScores; i++ ) { if ( cgs.clientinfo[cg.scores[i].client].team == TEAM_SPECTATOR ) specCount++; } s = va( "Players: %i/%i - %i spectators", cg.numScores, cgs.maxclients, specCount ); } CG_Text_Paint( x-(CG_Text_Width( s, 0.75f, FONT_NONE )/2), y+15, 0.75f, &colorTable[CT_WHITE], s, 0.0f, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_NONE ); s = va( "%s (%s)", (char *)CG_ConfigString( CS_MESSAGE ), cgs.mapname ); CG_Text_Paint( x-(CG_Text_Width( s, 0.75f, FONT_NONE )/2), y+30, 0.75f, &colorTable[CT_WHITE], s, 0.0f, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_NONE ); } // current rank if (cgs.gametype == GT_POWERDUEL) { //do nothing? } else if ( cgs.gametype < GT_TEAM) { #if 0 if (cg.snap->ps.persistant[PERS_TEAM] != TEAM_SPECTATOR ) { char sPlace[256]; char sOf[256]; char sWith[256]; trap->SE_GetStringTextString("MP_INGAME_PLACE", sPlace, sizeof(sPlace)); trap->SE_GetStringTextString("MP_INGAME_OF", sOf, sizeof(sOf)); trap->SE_GetStringTextString("MP_INGAME_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 = ( 480 ) / 2; // y = SB_HEADER-24; x = ( SCREEN_WIDTH ) / 2; y = SB_HEADER-24; //CG_DrawBigString( x, y, s, fade ); UI_DrawProportionalString(x, y, s, UI_CENTER|UI_DROPSHADOW, colorTable[CT_WHITE]); } #else #endif } else if (cgs.gametype != GT_SIEGE) { if ( cg.teamScores[0] == cg.teamScores[1] ) { s = va("%s %i", CG_GetStringEdString("MP_INGAME", "TIEDAT"), cg.teamScores[0] ); } else if ( cg.teamScores[0] >= cg.teamScores[1] ) { s = va("%s, %i / %i", CG_GetStringEdString("MP_INGAME", "RED_LEADS"), cg.teamScores[0], cg.teamScores[1] ); } else { s = va("%s, %i / %i", CG_GetStringEdString("MP_INGAME", "BLUE_LEADS"), cg.teamScores[1], cg.teamScores[0] ); } // x = ( 460 ) / 2; // y = SB_HEADER-24; x = ( SCREEN_WIDTH ) / 2; y = SB_HEADER-24; 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_SIEGE && (cg_siegeWinTeam == 1 || cg_siegeWinTeam == 2)) { if (cg_siegeWinTeam == 1) { s = va("%s", CG_GetStringEdString("MP_INGAME", "SIEGETEAM1WIN") ); } else { s = va("%s", CG_GetStringEdString("MP_INGAME", "SIEGETEAM2WIN") ); } 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_TOP-24; //SB_HEADER // CG_DrawPic ( SB_SCORELINE_X - 40, y - 5, SB_SCORELINE_WIDTH + 80, 40, trap->R_RegisterShaderNoMip ( "gfx/menus/menu_buttonback.tga" ) ); CG_Text_Paint ( SB_NAME_X, y, 1.0f, &colorWhite, CG_GetStringEdString("MP_INGAME", "NAME"),0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); if (cgs.gametype == GT_DUEL || cgs.gametype == GT_POWERDUEL) { char sWL[100]; trap->SE_GetStringTextString("MP_INGAME_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_GetStringEdString("MP_INGAME", "SCORE"), 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); } CG_Text_Paint ( SB_PING_X, y, 1.0f, &colorWhite, CG_GetStringEdString("MP_INGAME", "PING"), 0, 0, ITEM_TEXTSTYLE_OUTLINED, FONT_MEDIUM ); CG_Text_Paint ( SB_TIME_X, y, 1.0f, &colorWhite, CG_GetStringEdString("MP_INGAME", "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; } realMaxClients = maxClients; 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 ( cgs.gametype >= GT_TEAM ) { // // 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); } maxClients = realMaxClients; 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; }
// This function is called recursively when a logical message has to be split into multiple lines void CG_ChatboxAdd( const char *message, qboolean multiLine ) { chatEntry_t *chat = &chatbox.chatBuffer[MAX_CHATBOX_ENTRIES-1]; size_t strLength = 0; int i = 0; float accumLength = 0.0f; chatbox.numActiveLines++; //Stop scrolling up if we've already scrolled, similar to console behaviour if ( chatbox.scrollAmount < 0 ) chatbox.scrollAmount = MAX( chatbox.scrollAmount - 1, chatbox.numActiveLines >= cg_chatboxLineCount->integer ? ((MIN(chatbox.numActiveLines, MAX_CHATBOX_ENTRIES)-cg_chatboxLineCount->integer)*-1) : 0 ); //cb->scrollAmount--; for ( i=0, strLength=strlen( message ); i<strLength && i<CHAT_MESSAGE_LENGTH; i++ ) { char *p = (char*)&message[i]; char buf[1]; buf[0] = *p; if ( !Q_IsColorString( p ) && (i > 0 && !Q_IsColorString( p-1 )) ) accumLength += CG_Text_Width( buf, CHATBOX_FONT_SCALE, -1 ); if ( accumLength > SCREEN_WIDTH && (i>0 && !Q_IsColorString( p-1 )) ) { char lastColor = '2'; int j = i; int savedOffset = i; char tempMessage[CHAT_MESSAGE_LENGTH]; //Attempt to back-track, find a space (' ') within X characters or pixels //RAZTODO: Another method using character width? Meh while ( message[i] != ' ' ) { if ( i <= 0 || i < savedOffset-16 ) { i = j = savedOffset; break; } i--; j--; } memmove( &chatbox.chatBuffer[0], &chatbox.chatBuffer[1], sizeof( chatbox.chatBuffer ) - sizeof( chatEntry_t ) ); memset( chat, 0, sizeof( chatEntry_t ) ); //Clear the last element, ready for writing Q_strncpyz( chat->message, message, i+1 ); chat->time = cg.time + cg_chatboxMsgTime->integer*1000; chat->isUsed = qtrue; for ( j=i; j>=0; j-- ) { if ( message[j] == '^' && message[j+1] >= '0' && message[j+1] <= '9' ) { lastColor = message[j+1]; break; } } Com_sprintf( tempMessage, sizeof( tempMessage ), "^%c%s", lastColor, (const char *)(message + i) ); //Recursively insert until we don't have to split the message CG_ChatboxAdd( tempMessage, qtrue ); return; } } memmove( &chatbox.chatBuffer[0], &chatbox.chatBuffer[1], sizeof( chatbox.chatBuffer ) - sizeof( chatEntry_t ) ); memset( chat, 0, sizeof( chatEntry_t ) ); //Clear the last element, ready for writing Q_strncpyz( chat->message, message, i+1 ); chat->time = cg.time + cg_chatboxMsgTime->integer*1000; chat->isUsed = qtrue; }
int UI_DisplayContextCG::textWidth( const char *text, float scale, int limit ) { return CG_Text_Width( text, scale, limit ); }
// This function is called recursively when a logical message has to be split into multiple lines void JP_ChatboxAdd( const char *message, qboolean multiLine, char *cbName ) { chatBox_t *cb = GetChatboxByName( cbName ); chatEntry_t *chat = &cb->chatBuffer[MAX_CHATBOX_ENTRIES-1]; int strLength = 0; int i = 0; float accumLength = 0.0f; //cg_chatTimeStamp.integer ? CG_Text_Width( EXAMPLE_TIMESTAMP, cg_hudChatS.value, JP_GetChatboxFont() ) : 0.0f; char buf[CHAT_MESSAGE_LENGTH] = { 0 }; struct tm *timeinfo; time_t tm; accumLength = cg_chatboxTimeShow.integer ? CG_Text_Width( EXAMPLE_TIMESTAMP_CLEAN, cg.chatbox.size.scale, JP_GetChatboxFont() ) : 0.0f; cb->numActiveLines++; if ( cb != currentChatbox ) cb->notification = qtrue; //Stop scrolling up if we've already scrolled, similar to console behaviour if ( cb->scrollAmount < 0 ) cb->scrollAmount = max( cb->scrollAmount - 1, cb->numActiveLines >= cg_chatboxLineCount.integer ? ((min(cb->numActiveLines,MAX_CHATBOX_ENTRIES)-cg_chatboxLineCount.integer)*-1) : 0 ); //cb->scrollAmount--; for ( i=0, strLength=strlen( message ); i<strLength && i<CHAT_MESSAGE_LENGTH; i++ ) { char *p = (char*)&message[i]; Com_sprintf( buf, sizeof( buf ), "%c", *p ); if ( !Q_IsColorString( p ) && (i > 0 && !Q_IsColorString( p-1 )) ) accumLength += CG_Text_Width( buf, cg.chatbox.size.scale, JP_GetChatboxFont() ); //HACK: Compensate for ^x effectively being 0 // if ( Q_IsColorString( p ) ) // accumLength -= CG_Text_Width( "^0", chatVars.scale, JP_GetChatboxFont() ); if ( accumLength > max( cg.chatbox.size.width, 192.0f ) && (i>0 && !Q_IsColorString( p-1 )) ) { char lastColor = '2'; int j = i; int savedOffset = i; char tempMessage[CHAT_MESSAGE_LENGTH]; //Attempt to back-track, find a space (' ') within X characters or pixels //RAZTODO: Another method using character width? Meh while ( message[i] != ' ' ) { if ( i <= 0 || i < savedOffset-16 ) { i = j = savedOffset; break; } i--; j--; } memmove( &cb->chatBuffer[0], &cb->chatBuffer[1], sizeof( cb->chatBuffer ) - sizeof( chatEntry_t ) ); memset( chat, 0, sizeof( chatEntry_t ) ); //Clear the last element, ready for writing Q_strncpyz( chat->message, message, i+1 ); chat->time = cg.time + cg_chatbox.integer; if ( !multiLine ) {//Insert time-stamp, only for entries on the first line if ( cg_chatboxTimeShow.integer == 1 ) { time( &tm ); timeinfo = localtime ( &tm ); if ( !cg.japp.timestamp24Hour && timeinfo->tm_hour > 12 ) timeinfo->tm_hour -= 12; Com_sprintf( chat->timeStamp, sizeof( chat->timeStamp ), "[^%c%02i:%02i:%02i^7] ", *(char *)cg_chatboxTimeColour.string, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec ); } else if ( cg_chatboxTimeShow.integer == 2 ) { int msec, seconds, mins, hours; msec = cg.time-cgs.levelStartTime; seconds = msec / 1000; mins = seconds / 60; seconds -= mins * 60; hours = mins / 60; mins -= hours * 60; Com_sprintf( chat->timeStamp, sizeof( chat->timeStamp ), "[^%c%02i:%02i:%02i^7] ", *(char *)cg_chatboxTimeColour.string, hours, mins, seconds ); } } chat->isUsed = qtrue; for ( j=i; j>=0; j-- ) { if ( message[j] == '^' && message[j+1] >= '0' && message[j+1] <= '9' ) { lastColor = message[j+1]; break; } } Com_sprintf( tempMessage, sizeof( tempMessage ), "^%c%s", lastColor, (const char *)(message + i) ); //Recursively insert until we don't have to split the message JP_ChatboxAdd( tempMessage, qtrue, cbName ); return; } } memmove( &cb->chatBuffer[0], &cb->chatBuffer[1], sizeof( cb->chatBuffer ) - sizeof( chatEntry_t ) ); memset( chat, 0, sizeof( chatEntry_t ) ); //Clear the last element, ready for writing Q_strncpyz( chat->message, message, i+1 ); chat->time = cg.time + cg_chatbox.integer; if ( !multiLine ) {//Insert time-stamp, only for entries on the first line if ( cg_chatboxTimeShow.integer == 1 ) { time( &tm ); timeinfo = localtime ( &tm ); if ( !cg.japp.timestamp24Hour && timeinfo->tm_hour > 12 ) timeinfo->tm_hour -= 12; Com_sprintf( chat->timeStamp, sizeof( chat->timeStamp ), "[^%c%02i:%02i:%02i^7] ", *(char *)cg_chatboxTimeColour.string, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec ); } else if ( cg_chatboxTimeShow.integer == 2 ) { int msec, seconds, mins, hours; msec = cg.time-cgs.levelStartTime; seconds = msec / 1000; mins = seconds / 60; seconds -= mins * 60; hours = mins / 60; mins -= hours * 60; Com_sprintf( chat->timeStamp, sizeof( chat->timeStamp ), "[^%c%02i:%02i:%02i^7] ", *(char *)cg_chatboxTimeColour.string, hours, mins, seconds ); } } chat->isUsed = qtrue; }
/* ================= CG_DrawScoreboard ================= */ static void CG_DrawClientScore( int y, score_t *score, float *color, float fade, qboolean largeFormat ) { char string[1024]; vec3_t headAngles; clientInfo_t *ci; int iconx, headx; float scale = 0.35; int h = CG_Text_Height( "Tj", scale, 0 ); //int ty; if ( score->client < 0 || score->client >= cgs.maxclients ) { Com_Printf( "Bad score->client: %i\n", score->client ); return; } color[3] = fade; 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 - SB_LARGE_SPACER, SB_LARGE_ICON, SB_LARGE_ICON, TEAM_FREE, qfalse, SCR_CENTER ); } else { CG_DrawFlagModel( iconx, y - SB_SMALL_SPACER, SB_SMALL_ICON, SB_SMALL_ICON, TEAM_FREE, qfalse, SCR_CENTER ); } } else if ( ci->powerups & ( 1 << PW_REDFLAG ) ) { if( largeFormat ) { CG_DrawFlagModel( iconx, y - SB_LARGE_SPACER, SB_LARGE_ICON, SB_LARGE_ICON, TEAM_RED, qfalse, SCR_CENTER ); } else { CG_DrawFlagModel( iconx, y - SB_SMALL_SPACER, SB_SMALL_ICON, SB_SMALL_ICON, TEAM_RED, qfalse, SCR_CENTER ); } } else if ( ci->powerups & ( 1 << PW_BLUEFLAG ) ) { if( largeFormat ) { CG_DrawFlagModel( iconx, y - SB_LARGE_SPACER, SB_LARGE_ICON, SB_LARGE_ICON, TEAM_BLUE, qfalse, SCR_CENTER ); } else { CG_DrawFlagModel( iconx, y - SB_SMALL_SPACER, SB_SMALL_ICON, SB_SMALL_ICON, TEAM_BLUE, qfalse, SCR_CENTER ); } } else { if ( ci->botSkill > 0 && ci->botSkill <= 5 ) { if ( cg_drawIcons.integer ) { if( largeFormat ) { CG_DrawColorPic( iconx, y - SB_LARGE_SPACER, SB_LARGE_ICON, SB_LARGE_ICON, cgs.media.botSkillShaders[ci->botSkill - 1], SCR_CENTER, color ); } else { CG_DrawColorPic( iconx, y - SB_SMALL_SPACER, SB_SMALL_ICON, SB_SMALL_ICON, cgs.media.botSkillShaders[ci->botSkill - 1], SCR_CENTER, color ); } } } else if ( ci->handicap < 100 ) { Com_sprintf( string, sizeof( string ), "%i", ci->handicap ); if ( gt[cgs.gametype].duel ) { if ( cg_highResFonts.integer ) { CG_Text_Paint( iconx, y + h + ((float)h/2), scale, color, string, 0, 0, ITEM_TEXTSTYLE_SHADOWED, SCR_CENTER ); } else { CG_DrawSmallStringColor( iconx, y - SMALLCHAR_HEIGHT/2, string, color, SCR_CENTER ); } } else { if ( cg_highResFonts.integer ) { //w = CG_Text_Width(s, scale, 0); h = CG_Text_Height(string, scale, 0); CG_Text_Paint( iconx, y + h, scale, color, string, 0, 0, ITEM_TEXTSTYLE_SHADOWED, SCR_CENTER ); } else { CG_DrawSmallStringColor( iconx, y, string, color, SCR_CENTER ); } } } // draw the wins / losses if ( gt[cgs.gametype].duel ) { Com_sprintf( string, sizeof( string ), "%i/%i", ci->wins, ci->losses ); if ( ci->handicap < 100 && !ci->botSkill ) { if ( cg_highResFonts.integer ) { CG_Text_Paint( iconx, y + h + ((float)h/2), scale, color, string, 0, 0, ITEM_TEXTSTYLE_SHADOWED, SCR_CENTER ); } else { CG_DrawSmallStringColor( iconx, y + SMALLCHAR_HEIGHT/2, string, color, SCR_CENTER ); } } else { if ( cg_highResFonts.integer ) { CG_Text_Paint( iconx, y + h, scale, color, string, 0, 0, ITEM_TEXTSTYLE_SHADOWED, SCR_CENTER ); } else { CG_DrawSmallStringColor( iconx, y, string, color, SCR_CENTER ); } } } } // draw the face VectorClear( headAngles ); headAngles[YAW] = 180; if ( largeFormat ) { CG_DrawHead( headx, y - SB_LARGE_SPACER*2, ICON_SIZE, ICON_SIZE, score->client, headAngles, SCR_CENTER, color ); } else { CG_DrawHead( headx, y + SB_SMALL_SPACER, SB_SMALL_ICON, SB_SMALL_ICON, score->client, headAngles, SCR_CENTER, color ); } // draw the score line // 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 ) { 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.4f; hcolor[1] = 0.4f; hcolor[2] = 0.4f; } hcolor[3] = fade * 0.7; /* CG_DrawTeamBackground( SB_SCORELINE_X + BIGCHAR_WIDTH + (SB_RATING_WIDTH / 2), y, SCREEN_WIDTH - SB_SCORELINE_X - BIGCHAR_WIDTH, BIGCHAR_HEIGHT+1, 1, gt[cgs.gametype].teams ? cg.snap->ps.persistant[PERS_TEAM] : hcolor, SCR_CENTER ); */ CG_FillRect( SB_SCORELINE_X + BIGCHAR_WIDTH + (SB_RATING_WIDTH / 2), y, SCREEN_WIDTH - SB_SCORELINE_X - BIGCHAR_WIDTH, BIGCHAR_HEIGHT+2, gt[cgs.gametype].teams ? CG_TeamColorDark(cg.snap->ps.persistant[PERS_TEAM], fade) : hcolor, SCR_CENTER ); } // draw client score strings if ( cg_highResFonts.integer ) { qboolean spec = ci->team == TEAM_SPECTATOR; int w; char *s; // score s = (score->ping == -1) ? "CONN" : spec ? "SPEC" : cg.warmup ? "-" : va("%i", score->score); w = CG_Text_Width( s, scale, 0 ); CG_Text_Paint( SB_SCORE_X + (SB_RATING_WIDTH / 2) + 64-w, y + h, scale, color, s, 0, 0, ITEM_TEXTSTYLE_SHADOWED, SCR_CENTER ); // ping s = va( "%i", score->ping ); w = CG_Text_Width( s, scale, 0 ); CG_Text_Paint( SB_PING_X - (SB_RATING_WIDTH + BIGCHAR_WIDTH )/2 + 64-w, y + h, scale, color, s, 0, 0, ITEM_TEXTSTYLE_SHADOWED, SCR_CENTER ); // time s = va( "%i", score->time ); //CG_IntToTime( score->time*1000, qtrue, qfalse ); w = CG_Text_Width( s, scale, 0 ); CG_Text_Paint( SB_TIME_X - (SB_RATING_WIDTH + BIGCHAR_WIDTH )/2 + 64-w, y + h, scale, color, s, 0, 0, ITEM_TEXTSTYLE_SHADOWED, SCR_CENTER ); // name CG_Text_Paint( SB_NAME_X - (SB_RATING_WIDTH / 2), y + h, scale, color, ci->name, 0, 0, ITEM_TEXTSTYLE_SHADOWED, SCR_CENTER ); } else { if ( score->ping == -1 ) { Com_sprintf(string, sizeof(string), " connecting %s", ci->name); } else if ( ci->team == TEAM_SPECTATOR ) { Com_sprintf(string, sizeof(string), " SPECT %3i %4i %s", score->ping, score->time, ci->name); } else { Com_sprintf(string, sizeof(string), "%5i %4i %4i %s", score->score, score->ping, score->time, ci->name); } CG_DrawBigString( SB_SCORELINE_X + (SB_RATING_WIDTH / 2), y, string, fade, SCR_CENTER ); } // add the "ready" marker for intermission exiting if ( cg.snap->ps.stats[STAT_CLIENTS_READY] & ( 1 << score->client ) ) { if ( cg_highResFonts.integer ) { CG_Text_Paint( iconx, y + h, scale, color, "READY", 0, 0, ITEM_TEXTSTYLE_SHADOWED, SCR_CENTER ); } else { CG_DrawBigStringColor( iconx, y, "READY", color, SCR_CENTER ); } } }
void CG_DrawNewTeamInfo(rectDef_t *rect, float text_x, float text_y, float scale, vector4 *color, qhandle_t shader) { int i, j, count, xx; const char *p; vector4 hcolor; float pwidth, lwidth, maxx, leftOver, len, y; clientInfo_t *ci; const gitem_t *item; // max player name width pwidth = 0; count = (numSortedTeamPlayers > 8) ? 8 : numSortedTeamPlayers; for (i = 0; i < count; i++) { ci = cgs.clientinfo + sortedTeamPlayers[i]; if ( ci->infoValid && ci->team == cg.snap->ps.persistent[PERS_TEAM]) { len = CG_Text_Width( ci->name, scale, 0); if (len > pwidth) pwidth = (float)len; } } // max location name width lwidth = 0; for (i = 1; i < MAX_LOCATIONS; i++) { p = CG_ConfigString(CS_LOCATIONS + i); if (p && *p) { len = CG_Text_Width(p, scale, 0); if (len > lwidth) lwidth = (float)len; } } y = rect->y; for (i = 0; i < count; i++) { ci = cgs.clientinfo + sortedTeamPlayers[i]; if ( ci->infoValid && ci->team == cg.snap->ps.persistent[PERS_TEAM]) { xx = (int)rect->x + 1; for (j = 0; j <= PW_NUM_POWERUPS; j++) { if (ci->powerups & (1 << j)) { item = BG_FindItemForPowerup( j ); if (item) { CG_DrawPic( (float)xx, y, PIC_WIDTH, PIC_WIDTH, trap->R_RegisterShader( item->icon ) ); xx += PIC_WIDTH; } } } // FIXME: max of 3 powerups shown properly xx = (int)rect->x + (PIC_WIDTH * 3) + 2; CG_GetColorForHealth( ci->health, ci->armor, &hcolor ); trap->R_SetColor(&hcolor); CG_DrawPic( (float)xx, y + 1, PIC_WIDTH - 2, PIC_WIDTH - 2, cgs.media.heartShader ); //Com_sprintf (st, sizeof(st), "%3i %3i", ci->health, ci->armor); //CG_Text_Paint(xx, y + text_y, scale, hcolor, st, 0, 0); // draw weapon icon xx += PIC_WIDTH + 1; // weapon used is not that useful, use the space for task #if 0 if ( cg_weapons[ci->curWeapon].weaponIcon ) { CG_DrawPic( xx, y, PIC_WIDTH, PIC_WIDTH, cg_weapons[ci->curWeapon].weaponIcon ); } else { CG_DrawPic( xx, y, PIC_WIDTH, PIC_WIDTH, cgs.media.deferShader ); } #endif trap->R_SetColor(NULL); leftOver = rect->w - xx; maxx = xx + leftOver / 3; CG_Text_Paint_Limit(&maxx, (float)xx, y + text_y, scale, color, ci->name, 0, 0); p = CG_ConfigString(CS_LOCATIONS + ci->location); if (!p || !*p) { p = "unknown"; } xx += (int)(leftOver/3 + 2); maxx = rect->w - 4; CG_Text_Paint_Limit(&maxx, (float)xx, y + text_y, scale, color, p, 0, 0); y += text_y + 2; if ( y + text_y + 2 > rect->y + rect->h ) { break; } } } }
/* ================= CG_DrawQ3Scoreboard Draw the normal in-game scoreboard ================= */ qboolean CG_DrawQ3Scoreboard( void ) { int x, y, w, i, n1, n2; float *fadeColor, fade; char *s; int maxClients; int lineHeight; int topBorderSize, bottomBorderSize; // don't draw anything if the menu or console is up if ( cg_paused.integer ) { cg.deferredPlayerLoading = 0; return qfalse; } if ( cgs.gametype == GT_SINGLE_PLAYER && cg.predictedPlayerState.pm_type == PM_INTERMISSION ) { cg.deferredPlayerLoading = 0; return qfalse; } // don't draw scoreboard during death while warmup up if ( cg.warmup && !cg.showScores && cg.time > cg.scoreFadeTime + FADE_TIME ) { return qfalse; } //#if 0 if ( cg.showScores || cg.predictedPlayerState.pm_type == PM_DEAD || cg.predictedPlayerState.pm_type == PM_INTERMISSION ) { 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; } } //#endif //fadeColor = colorWhite; fade = fadeColor[3]; //#if 0 // request more scores regularly if ( cg.scoresRequestTime + 2000 < cg.time ) { cg.scoresRequestTime = cg.time; trap_SendClientCommand( "score" ); } //CG_Printf( "scoresRequestTime = %i\n", cg.scoresRequestTime ); //CG_Printf( "scoreFadeTime = %i, fade = %f\n", cg.scoreFadeTime, fade ); //#endif // fragged by ... line if ( !cg.warmup ) { if ( cg.killerName[0] ) { s = va( "Fragged by %s", cg.killerName ); y = 40; if ( cg_highResFonts.integer ) { float scale = 0.35; int h; w = CG_Text_Width(s, scale, 0); h = CG_Text_Height(s, scale, 0); x = (SCREEN_WIDTH - w) / 2; CG_Text_Paint( x, y + h, scale, fadeColor, s, 0, 0, ITEM_TEXTSTYLE_SHADOWED, SCR_CENTER ); } else { w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; x = ( SCREEN_WIDTH - w ) / 2; CG_DrawBigString( x, y, s, fade, SCR_CENTER ); } } // current rank { s = CG_GetGameStatusText(); if ( s[0] ) { y = 60; if ( cg_highResFonts.integer ) { float scale = 0.35f; int h; w = CG_Text_Width(s, scale, 0); h = CG_Text_Height(s, scale, 0); x = (SCREEN_WIDTH - w) / 2; CG_Text_Paint( x, y + h, scale, fadeColor, s, 0, 0, ITEM_TEXTSTYLE_SHADOWED, SCR_CENTER ); } else { w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; x = ( SCREEN_WIDTH - w ) / 2; CG_DrawBigString( x, y, s, fade, SCR_CENTER ); } } } } // scoreboard y = SB_HEADER; CG_DrawColorPic( SB_SCORE_X + (SB_RATING_WIDTH / 2), y, 64, 32, cgs.media.scoreboardScore, SCR_CENTER, fadeColor ); CG_DrawColorPic( SB_PING_X - (SB_RATING_WIDTH / 2), y, 64, 32, cgs.media.scoreboardPing, SCR_CENTER, fadeColor ); CG_DrawColorPic( SB_TIME_X - (SB_RATING_WIDTH / 2), y, 64, 32, cgs.media.scoreboardTime, SCR_CENTER, fadeColor ); CG_DrawColorPic( SB_NAME_X - (SB_RATING_WIDTH / 2), y, 64, 32, cgs.media.scoreboardName, SCR_CENTER, fadeColor ); 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 = 16; bottomBorderSize = 16; } localClient = qfalse; if ( gt[cgs.gametype].teams ) { float team_opacity = 0.33f; // // teamplay scoreboard // y += lineHeight/2; if ( cg.teamScores[0] >= cg.teamScores[1] ) { n1 = CG_TeamScoreCount( TEAM_RED, maxClients ); CG_DrawTeamBackground( 0, y - topBorderSize, SCREEN_WIDTH, n1 * lineHeight + bottomBorderSize, team_opacity, TEAM_RED, SCR_NONE ); CG_TeamScoreboard( y, TEAM_RED, fade, maxClients, lineHeight ); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; maxClients -= n1; n2 = CG_TeamScoreCount( TEAM_BLUE, maxClients ); CG_DrawTeamBackground( 0, y - topBorderSize, SCREEN_WIDTH, n2 * lineHeight + bottomBorderSize, team_opacity, TEAM_BLUE, SCR_NONE ); CG_TeamScoreboard( y, TEAM_BLUE, fade, maxClients, lineHeight ); y += (n2 * lineHeight) + BIGCHAR_HEIGHT; maxClients -= n2; } else { n1 = CG_TeamScoreCount( TEAM_BLUE, maxClients ); CG_DrawTeamBackground( 0, y - topBorderSize, SCREEN_WIDTH, n1 * lineHeight + bottomBorderSize, team_opacity, TEAM_BLUE, SCR_NONE ); CG_TeamScoreboard( y, TEAM_BLUE, fade, maxClients, lineHeight ); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; maxClients -= n1; n2 = CG_TeamScoreCount( TEAM_RED, maxClients ); CG_DrawTeamBackground( 0, y - topBorderSize, SCREEN_WIDTH, n2 * lineHeight + bottomBorderSize, team_opacity, TEAM_RED, SCR_NONE ); CG_TeamScoreboard( y, TEAM_RED, fade, maxClients, lineHeight ); y += (n2 * lineHeight) + BIGCHAR_HEIGHT; maxClients -= n2; } /* n1 = CG_TeamScoreCount( TEAM_SPECTATOR, maxClients ); CG_TeamScoreboard( y, TEAM_SPECTATOR, fade, maxClients, lineHeight ); */ n1 = CG_TeamScoreboard( y, TEAM_SPECTATOR, fade, maxClients, lineHeight ); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; } else { // // free for all scoreboard // /* n1 = CG_TeamScoreCount( TEAM_SPECTATOR, maxClients ); CG_TeamScoreboard( y, TEAM_FREE, fade, maxClients, lineHeight ); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; n2 = CG_TeamScoreCount( TEAM_SPECTATOR, maxClients ); CG_TeamScoreboard( y, TEAM_SPECTATOR, fade, maxClients - n1, lineHeight ); y += (n2 * lineHeight) + BIGCHAR_HEIGHT; */ n1 = CG_TeamScoreboard( y, TEAM_FREE, fade, maxClients, lineHeight ); y += (n1 * lineHeight) + BIGCHAR_HEIGHT; n2 = CG_TeamScoreboard( y, TEAM_SPECTATOR, fade, maxClients - n1, lineHeight ); 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; }