// // Draw Weapon Menu // int CHudAmmo::DrawWList( float flTime ) { int r, g, b, a; int x, y, i; if( !gpActiveSel ) return 0; int iActiveSlot; if( gpActiveSel == (WEAPON *)1 ) iActiveSlot = -1; // current slot has no weapons else iActiveSlot = gpActiveSel->iSlot; x = 10; //!!! y = 10; //!!! // Ensure that there are available choices in the active slot if( iActiveSlot > 0 ) { if( !gWR.GetFirstPos( iActiveSlot )) { gpActiveSel = (WEAPON *)1; iActiveSlot = -1; } } // Draw top line for( i = 0; i < MAX_WEAPON_SLOTS; i++ ) { int iWidth; UnpackRGB( r, g, b, gHUD.m_iHUDColor ); if( iActiveSlot == i ) a = 255; else a = 192; ScaleColors( r, g, b, 255 ); SPR_Set( gHUD.GetSprite( m_HUD_bucket0 + i ), r, g, b ); // make active slot wide enough to accomodate gun pictures if( i == iActiveSlot ) { WEAPON *p = gWR.GetFirstPos(iActiveSlot); if( p ) iWidth = p->rcActive.right - p->rcActive.left; else iWidth = giBucketWidth; } else iWidth = giBucketWidth; SPR_DrawAdditive( 0, x, y, &gHUD.GetSpriteRect( m_HUD_bucket0 + i )); x += iWidth + 5; } a = 128; //!!! x = 10; // Draw all of the buckets for( i = 0; i < MAX_WEAPON_SLOTS; i++ ) { y = giBucketHeight + 10; // If this is the active slot, draw the bigger pictures, // otherwise just draw boxes if( i == iActiveSlot ) { WEAPON *p = gWR.GetFirstPos( i ); int iWidth = giBucketWidth; if( p ) iWidth = p->rcActive.right - p->rcActive.left; for( int iPos = 0; iPos < MAX_WEAPON_POSITIONS; iPos++ ) { p = gWR.GetWeaponSlot( i, iPos ); if( !p || !p->iId ) continue; UnpackRGB( r, g, b, gHUD.m_iHUDColor ); // if active, then we must have ammo. if( gpActiveSel == p ) { SPR_Set( p->hActive, r, g, b ); SPR_DrawAdditive( 0, x, y, &p->rcActive ); SPR_Set( gHUD.GetSprite( m_HUD_selection ), r, g, b ); SPR_DrawAdditive( 0, x, y, &gHUD.GetSpriteRect( m_HUD_selection )); } else { // Draw Weapon if Red if no ammo if( gWR.HasAmmo( p )) { ScaleColors( r, g, b, 192 ); } else { UnpackRGB( r, g, b, RGB_REDISH ); ScaleColors( r, g, b, 128 ); } SPR_Set( p->hInactive, r, g, b ); SPR_DrawAdditive( 0, x, y, &p->rcInactive ); } // Draw Ammo Bar DrawAmmoBar( p, x + giABWidth / 2, y, giABWidth, giABHeight ); y += p->rcActive.bottom - p->rcActive.top + 5; } x += iWidth + 5; } else { // Draw Row of weapons. UnpackRGB( r, g, b, gHUD.m_iHUDColor ); for( int iPos = 0; iPos < MAX_WEAPON_POSITIONS; iPos++ ) { WEAPON *p = gWR.GetWeaponSlot( i, iPos ); if( !p || !p->iId ) continue; if( gWR.HasAmmo( p )) { UnpackRGB( r, g, b, gHUD.m_iHUDColor ); a = 128; } else { UnpackRGB( r, g, b, RGB_REDISH ); a = 96; } FillRGBA( x, y, giBucketWidth, giBucketHeight, r, g, b, a ); y += giBucketHeight + 5; } x += giBucketWidth + 5; } } return 1; }
//------------------------------------------------------------------------- // Drawing code //------------------------------------------------------------------------- int CHudAmmo::Draw( float flTime ) { int a, x, y, r, g, b; int AmmoWidth; if (!(gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT)) )) return 1; if(( gHUD.m_iHideHUDDisplay & ( HIDEHUD_WEAPONS | HIDEHUD_ALL ))) return 1; // Draw Weapon Menu DrawWList( flTime ); // Draw ammo pickup history gHR.DrawAmmoHistory( flTime ); if( !( m_iFlags & HUD_ACTIVE )) return 0; if( !m_pWeapon ) { return 0; } WEAPON *pw = m_pWeapon; // shorthand // SPR_Draw Ammo if(( pw->iAmmoType < 0 ) && ( pw->iAmmo2Type < 0 )) return 0; int iFlags = DHN_DRAWZERO; // draw 0 values AmmoWidth = gHUD.GetSpriteRect( gHUD.m_HUD_number_0 ).right - gHUD.GetSpriteRect( gHUD.m_HUD_number_0 ).left; a = (int)max( MIN_ALPHA, m_fFade ); if( m_fFade > 0 ) m_fFade -= (gHUD.m_flTimeDelta * 20); UnpackRGB( r, g, b, gHUD.m_iHUDColor ); ScaleColors( r, g, b, a ); // Does this weapon have a clip? y = ScreenHeight - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2; // Does weapon have any ammo at all? if( m_pWeapon->iAmmoType > 0 ) { int iIconWidth = m_pWeapon->rcAmmo.right - m_pWeapon->rcAmmo.left; if( pw->iClip >= 0 ) { // room for the number and the '|' and the current ammo x = ScreenWidth - ( 8 * AmmoWidth ) - iIconWidth; x = gHUD.DrawHudNumber( x, y, iFlags | DHN_3DIGITS, pw->iClip, r, g, b ); wrect_t rc; rc.top = 0; rc.left = 0; rc.right = AmmoWidth; rc.bottom = 100; int iBarWidth = AmmoWidth / 10; x += AmmoWidth / 2; UnpackRGB( r, g, b, gHUD.m_iHUDColor ); // draw the | bar FillRGBA( x, y, iBarWidth, gHUD.m_iFontHeight, r, g, b, a ); x += iBarWidth + AmmoWidth / 2; // GL Seems to need this ScaleColors( r, g, b, a ); x = gHUD.DrawHudNumber( x, y, iFlags | DHN_3DIGITS, gWR.CountAmmo( pw->iAmmoType ), r, g, b ); } else { // SPR_Draw a bullets only line x = ScreenWidth - 4 * AmmoWidth - iIconWidth; x = gHUD.DrawHudNumber(x, y, iFlags | DHN_3DIGITS, gWR.CountAmmo( pw->iAmmoType ), r, g, b ); } // Draw the ammo Icon int iOffset = ( m_pWeapon->rcAmmo.bottom - m_pWeapon->rcAmmo.top ) / 8; SPR_Set( m_pWeapon->hAmmo, r, g, b ); SPR_DrawAdditive( 0, x, y - iOffset, &m_pWeapon->rcAmmo ); } // Does weapon have seconday ammo? if( pw->iAmmo2Type > 0 ) { int iIconWidth = m_pWeapon->rcAmmo2.right - m_pWeapon->rcAmmo2.left; // Do we have secondary ammo? if(( pw->iAmmo2Type != 0 ) && ( gWR.CountAmmo(pw->iAmmo2Type ) > 0)) { y -= gHUD.m_iFontHeight + gHUD.m_iFontHeight / 4; x = ScreenWidth - 4 * AmmoWidth - iIconWidth; x = gHUD.DrawHudNumber( x, y, iFlags|DHN_3DIGITS, gWR.CountAmmo( pw->iAmmo2Type ), r, g, b ); // Draw the ammo Icon SPR_Set( m_pWeapon->hAmmo2, r, g, b ); int iOffset = ( m_pWeapon->rcAmmo2.bottom - m_pWeapon->rcAmmo2.top ) / 8; SPR_DrawAdditive( 0, x, y - iOffset, &m_pWeapon->rcAmmo2 ); } } return 1; }
int CHudHealth::Draw(float flTime) { int r, g, b; int a = 0, x, y; int HealthWidth; if ( (gHUD.m_iHideHUDDisplay & HIDEHUD_HEALTH) || gEngfuncs.IsSpectateOnly() ) return 1; if ( !m_hSprite ) m_hSprite = LoadSprite(PAIN_NAME); // Has health changed? Flash the health # if (m_fFade) { m_fFade -= (gHUD.m_flTimeDelta * 20); if (m_fFade <= 0) { a = MIN_ALPHA; m_fFade = 0; } // Fade the health number back to dim a = MIN_ALPHA + (m_fFade/FADE_TIME) * 128; } else a = MIN_ALPHA; // If health is getting low, make it bright red if (m_iHealth <= 15) a = 255; GetPainColor( r, g, b ); ScaleColors(r, g, b, a ); // Only draw health if we have the suit. if (gHUD.m_iWeaponBits & (1<<(WEAPON_SUIT))) { HealthWidth = gHUD.GetSpriteRect(gHUD.m_HUD_number_0).right - gHUD.GetSpriteRect(gHUD.m_HUD_number_0).left; int CrossWidth = gHUD.GetSpriteRect(m_HUD_cross).right - gHUD.GetSpriteRect(m_HUD_cross).left; y = ScreenHeight - gHUD.m_iFontHeight - gHUD.m_iFontHeight / 2; x = CrossWidth /2; SPR_Set(gHUD.GetSprite(m_HUD_cross), r, g, b); SPR_DrawAdditive(0, x, y, &gHUD.GetSpriteRect(m_HUD_cross)); x = CrossWidth + HealthWidth / 2; x = gHUD.DrawHudNumber(x, y, DHN_3DIGITS | DHN_DRAWZERO, m_iHealth, r, g, b); x += HealthWidth/2; int iHeight = gHUD.m_iFontHeight; int iWidth = HealthWidth/10; FillRGBA(x, y, iWidth, iHeight, 255, 160, 0, a); } DrawDamage(flTime); return DrawPain(flTime); }
/* ================= UI_Crosshair_Ownerdraw ================= */ static void UI_Crosshair_Ownerdraw( void *self ) { menuBitmap_s *item = (menuBitmap_s*)self; UI_DrawPic(item->generic.x, item->generic.y, item->generic.width, item->generic.height, 0x00FFFFFF, "gfx/vgui/crosshair" ); int l; switch( (int)uiPlayerSetup.crosshairSize.curValue ) { case 1: l = 10; break; case 2: l = 20; break; case 3: l = 30; break; case 0: if( ScreenWidth < 640 ) l = 30; else if( ScreenWidth < 1024 ) l = 20; else l = 10; } l *= ScreenHeight / 768.0f; int x = item->generic.x, // xpos y = item->generic.y, // ypos w = item->generic.width, // width h = item->generic.height, // height // delta distance d = (item->generic.width / 2 - l) * 0.5, // alpha a = 180, // red r = g_iCrosshairAvailColors[(int)uiPlayerSetup.crosshairColor.curValue][0], // green g = g_iCrosshairAvailColors[(int)uiPlayerSetup.crosshairColor.curValue][1], // blue b = g_iCrosshairAvailColors[(int)uiPlayerSetup.crosshairColor.curValue][2]; if( uiPlayerSetup.crosshairTranslucent.enabled ) { // verical PIC_Set(uiPlayerSetup.uiWhite, r, g, b, a); PIC_DrawTrans(x + w / 2, y + d, 1, l ); PIC_Set(uiPlayerSetup.uiWhite, r, g, b, a); PIC_DrawTrans(x + w / 2, y + h / 2 + d, 1, l ); // horizontal PIC_Set(uiPlayerSetup.uiWhite, r, g, b, a); PIC_DrawTrans(x + d, y + h / 2, l, 1 ); PIC_Set(uiPlayerSetup.uiWhite, r, g, b, a); PIC_DrawTrans(x + w / 2 + d, y + h / 2, l, 1 ); } else { // verical PIC_Set(uiPlayerSetup.uiWhite, r, g, b, a); PIC_DrawAdditive(x + w / 2, y + d, 1, l ); PIC_Set(uiPlayerSetup.uiWhite, r, g, b, a); PIC_DrawAdditive(x + w / 2, y + h / 2 + d, 1, l ); // horizontal PIC_Set(uiPlayerSetup.uiWhite, r, g, b, a); PIC_DrawAdditive(x + d, y + h / 2, l, 1 ); PIC_Set(uiPlayerSetup.uiWhite, r, g, b, a); PIC_DrawAdditive(x + w / 2 + d, y + h / 2, l, 1 ); } #if 0 // verical FillRGBA(x + w / 2, y + d, 1, l, r, g, b, a); FillRGBA(x + w / 2, y + h / 2 + d, 1, l, r, g, b, a); // horizontal FillRGBA(x + d, y + h / 2, l, 1, r, g, b, a); FillRGBA(x + w / 2 + d, y + h / 2, l, 1, r, g, b, a); #endif }
// returns the ypos where it finishes drawing int CHudScoreboard::DrawPlayers(int xpos_rel, float list_slot, int nameoffset, char *team) { int can_show_packetloss = 0; int FAR_RIGHT; // Packetloss removed on Kelly 'shipping nazi' Bailey's orders if(cl_showpacketloss && cl_showpacketloss->value && (ScreenWidth >= 400)) { can_show_packetloss = 1; SCOREBOARD_WIDTH = 400; } else { SCOREBOARD_WIDTH = 320; } FAR_RIGHT = can_show_packetloss ? PL_RANGE_MAX : PING_RANGE_MAX; FAR_RIGHT += 5; // draw the players, in order, and restricted to team if set while(1) { // Find the top ranking player int highest_frags = -99999; int lowest_deaths = 99999; int best_player = 0; for(int i = 1; i < MAX_PLAYERS; i++) { if(g_PlayerInfoList[i].name && g_PlayerExtraInfo[i].frags >= highest_frags) { if(!(team && stricmp(g_PlayerExtraInfo[i].teamname, team))) // make sure it is the specified team { extra_player_info_t *pl_info = &g_PlayerExtraInfo[i]; if(pl_info->frags > highest_frags || pl_info->deaths < lowest_deaths) { best_player = i; lowest_deaths = pl_info->deaths; highest_frags = pl_info->frags; } } } } if(!best_player) break; // draw out the best player hud_player_info_t *pl_info = &g_PlayerInfoList[best_player]; int ypos = ROW_RANGE_MIN + (list_slot * ROW_GAP); // check we haven't drawn too far down if(ypos > ROW_RANGE_MAX) // don't draw to close to the lower border break; int xpos = NAME_RANGE_MIN + xpos_rel; int r = 255, g = 255, b = 255; if(best_player == m_iLastKilledBy && m_fLastKillTime && m_fLastKillTime > gHUD.m_flTime) { if(pl_info->thisplayer) { // green is the suicide color? i wish this could do grey... FillRGBA(NAME_RANGE_MIN + xpos_rel - 5, ypos, FAR_RIGHT, ROW_GAP, 80, 155, 0, 70); } else { // Highlight the killers name - overlay the background in red, then draw the score text over it FillRGBA(NAME_RANGE_MIN + xpos_rel - 5, ypos, FAR_RIGHT, ROW_GAP, 255, 0, 0, ((float)15 * (float)(m_fLastKillTime - gHUD.m_flTime))); } } else if(pl_info->thisplayer) // if it is their name, draw it a different color { // overlay the background in blue, then draw the score text over it FillRGBA(NAME_RANGE_MIN + xpos_rel - 5, ypos, FAR_RIGHT, ROW_GAP, 0, 0, 255, 70); } // draw their name (left to right) gHUD.DrawHudString(xpos + nameoffset, ypos, NAME_RANGE_MAX + xpos_rel, pl_info->name, r, g, b); // draw kills (right to left) xpos = KILLS_RANGE_MAX + xpos_rel; gHUD.DrawHudNumberString(xpos, ypos, KILLS_RANGE_MIN + xpos_rel, g_PlayerExtraInfo[best_player].frags, r, g, b); // draw divider xpos = DIVIDER_POS + xpos_rel; gHUD.DrawHudString(xpos, ypos, xpos + 20, "/", r, g, b); // draw deaths xpos = DEATHS_RANGE_MAX + xpos_rel; gHUD.DrawHudNumberString(xpos, ypos, DEATHS_RANGE_MIN + xpos_rel, g_PlayerExtraInfo[best_player].deaths, r, g, b); // draw ping & packetloss static char buf[64]; sprintf(buf, "%d", g_PlayerInfoList[best_player].ping); xpos = ((PING_RANGE_MAX - PING_RANGE_MIN) / 2) + PING_RANGE_MIN + xpos_rel + 25; gHUD.DrawHudStringReverse(xpos, ypos, xpos - 50, buf, r, g, b); // Packetloss removed on Kelly 'shipping nazi' Bailey's orders if(can_show_packetloss) { if(g_PlayerInfoList[best_player].packetloss >= 63) { UnpackRGB(r, g, b, RGB_REDISH); sprintf(buf, " !!!!"); } else { sprintf(buf, " %d", g_PlayerInfoList[best_player].packetloss); } xpos = ((PL_RANGE_MAX - PL_RANGE_MIN) / 2) + PL_RANGE_MIN + xpos_rel + 25; gHUD.DrawHudString(xpos, ypos, xpos + 50, buf, r, g, b); } pl_info->name = NULL; // set the name to be NULL, so this client won't get drawn again list_slot++; } return list_slot; }
int CHudScoreboard::Draw(float fTime) { int can_show_packetloss = 0; int FAR_RIGHT; if(!m_iShowscoresHeld && gHUD.m_Health.m_iHealth > 0 && !gHUD.m_iIntermission) return 1; GetAllPlayersInfo(); // Packetloss removed on Kelly 'shipping nazi' Bailey's orders if(cl_showpacketloss && cl_showpacketloss->value && (ScreenWidth >= 400)) { can_show_packetloss = 1; SCOREBOARD_WIDTH = 400; } else { SCOREBOARD_WIDTH = 320; } // just sort the list on the fly // list is sorted first by frags, then by deaths float list_slot = 0; int xpos_rel = (ScreenWidth - SCOREBOARD_WIDTH) / 2; // print the heading line int ypos = ROW_RANGE_MIN + (list_slot * ROW_GAP); int xpos = NAME_RANGE_MIN + xpos_rel; if(!gHUD.m_Teamplay) gHUD.DrawHudString(xpos, ypos, NAME_RANGE_MAX + xpos_rel, "Player", 255, 140, 0); else gHUD.DrawHudString(xpos, ypos, NAME_RANGE_MAX + xpos_rel, "Teams", 255, 140, 0); gHUD.DrawHudStringReverse(KILLS_RANGE_MAX + xpos_rel, ypos, 0, "kills", 255, 140, 0); gHUD.DrawHudString(DIVIDER_POS + xpos_rel, ypos, ScreenWidth, "/", 255, 140, 0); gHUD.DrawHudString(DEATHS_RANGE_MIN + xpos_rel + 5, ypos, ScreenWidth, "deaths", 255, 140, 0); gHUD.DrawHudString(PING_RANGE_MAX + xpos_rel - 35, ypos, ScreenWidth, "latency", 255, 140, 0); if(can_show_packetloss) { gHUD.DrawHudString(PL_RANGE_MAX + xpos_rel - 35, ypos, ScreenWidth, "pkt loss", 255, 140, 0); } FAR_RIGHT = can_show_packetloss ? PL_RANGE_MAX : PING_RANGE_MAX; FAR_RIGHT += 5; list_slot += 1.2; ypos = ROW_RANGE_MIN + (list_slot * ROW_GAP); xpos = NAME_RANGE_MIN + xpos_rel; FillRGBA(xpos - 5, ypos, FAR_RIGHT, 1, 255, 140, 0, 255); // draw the seperator line list_slot += 0.8; if(!gHUD.m_Teamplay) { // it's not teamplay, so just draw a simple player list DrawPlayers(xpos_rel, list_slot); return 1; } // clear out team scores for(int i = 1; i <= m_iNumTeams; i++) { if(!g_TeamInfo[i].scores_overriden) g_TeamInfo[i].frags = g_TeamInfo[i].deaths = 0; g_TeamInfo[i].ping = g_TeamInfo[i].packetloss = 0; } // recalc the team scores, then draw them for(i = 1; i < MAX_PLAYERS; i++) { if(g_PlayerInfoList[i].name == NULL) continue; // empty player slot, skip if(g_PlayerExtraInfo[i].teamname[0] == 0) continue; // skip over players who are not in a team // find what team this player is in for(int j = 1; j <= m_iNumTeams; j++) { if(!stricmp(g_PlayerExtraInfo[i].teamname, g_TeamInfo[j].name)) break; } if(j > m_iNumTeams) // player is not in a team, skip to the next guy continue; if(!g_TeamInfo[j].scores_overriden) { g_TeamInfo[j].frags += g_PlayerExtraInfo[i].frags; g_TeamInfo[j].deaths += g_PlayerExtraInfo[i].deaths; } g_TeamInfo[j].ping += g_PlayerInfoList[i].ping; g_TeamInfo[j].packetloss += g_PlayerInfoList[i].packetloss; if(g_PlayerInfoList[i].thisplayer) g_TeamInfo[j].ownteam = TRUE; else g_TeamInfo[j].ownteam = FALSE; } // find team ping/packetloss averages for(i = 1; i <= m_iNumTeams; i++) { g_TeamInfo[i].already_drawn = FALSE; if(g_TeamInfo[i].players > 0) { g_TeamInfo[i].ping /= g_TeamInfo[i].players; // use the average ping of all the players in the team as the teams ping g_TeamInfo[i].packetloss /= g_TeamInfo[i].players; // use the average ping of all the players in the team as the teams ping } } // Draw the teams while(1) { int highest_frags = -99999; int lowest_deaths = 99999; int best_team = 0; for(i = 1; i <= m_iNumTeams; i++) { if(g_TeamInfo[i].players < 0) continue; if(!g_TeamInfo[i].already_drawn && g_TeamInfo[i].frags >= highest_frags) { if(g_TeamInfo[i].frags > highest_frags || g_TeamInfo[i].deaths < lowest_deaths) { best_team = i; lowest_deaths = g_TeamInfo[i].deaths; highest_frags = g_TeamInfo[i].frags; } } } // draw the best team on the scoreboard if(!best_team) break; // draw out the best team team_info_t *team_info = &g_TeamInfo[best_team]; ypos = ROW_RANGE_MIN + (list_slot * ROW_GAP); // check we haven't drawn too far down if(ypos > ROW_RANGE_MAX) // don't draw to close to the lower border break; xpos = NAME_RANGE_MIN + xpos_rel; int r = 255, g = 225, b = 55; // draw the stuff kinda yellowish if(team_info->ownteam) // if it is their team, draw the background different color { // overlay the background in blue, then draw the score text over it FillRGBA(NAME_RANGE_MIN + xpos_rel - 5, ypos, FAR_RIGHT, ROW_GAP, 0, 0, 255, 70); } // draw their name (left to right) gHUD.DrawHudString(xpos, ypos, NAME_RANGE_MAX + xpos_rel, team_info->name, r, g, b); // draw kills (right to left) xpos = KILLS_RANGE_MAX + xpos_rel; gHUD.DrawHudNumberString(xpos, ypos, KILLS_RANGE_MIN + xpos_rel, team_info->frags, r, g, b); // draw divider xpos = DIVIDER_POS + xpos_rel; gHUD.DrawHudString(xpos, ypos, xpos + 20, "/", r, g, b); // draw deaths xpos = DEATHS_RANGE_MAX + xpos_rel; gHUD.DrawHudNumberString(xpos, ypos, DEATHS_RANGE_MIN + xpos_rel, team_info->deaths, r, g, b); // draw ping // draw ping & packetloss static char buf[64]; sprintf(buf, "%d", team_info->ping); xpos = ((PING_RANGE_MAX - PING_RANGE_MIN) / 2) + PING_RANGE_MIN + xpos_rel + 25; UnpackRGB(r, g, b, RGB_YELLOWISH); gHUD.DrawHudStringReverse(xpos, ypos, xpos - 50, buf, r, g, b); // Packetloss removed on Kelly 'shipping nazi' Bailey's orders if(can_show_packetloss) { xpos = ((PL_RANGE_MAX - PL_RANGE_MIN) / 2) + PL_RANGE_MIN + xpos_rel + 25; sprintf(buf, " %d", team_info->packetloss); gHUD.DrawHudString(xpos, ypos, xpos + 50, buf, r, g, b); } team_info->already_drawn = TRUE; // set the already_drawn to be TRUE, so this team won't get drawn again list_slot++; // draw all the players that belong to this team, indented slightly list_slot = DrawPlayers(xpos_rel, list_slot, 10, team_info->name); } // draw all the players who are not in a team list_slot += 0.5; DrawPlayers(xpos_rel, list_slot, 0, ""); return 1; }