#include #include #include #include #include #include #include #include "scoreboard.hpp" SCOREBOARD::SCOREBOARD() { on_reset(); } void SCOREBOARD::con_key_scoreboard(void *result, void *user_data) { ((SCOREBOARD *)user_data)->active = console_arg_int(result, 0) != 0; } void SCOREBOARD::on_reset() { active = false; } void SCOREBOARD::on_init() { MACRO_REGISTER_COMMAND("+scoreboard", "", con_key_scoreboard, this); } void SCOREBOARD::render_goals(float x, float y, float w) { float h = 50.0f; gfx_blend_normal(); gfx_texture_set(-1); gfx_quads_begin(); gfx_setcolor(0,0,0,0.5f); draw_round_rect(x-10.f, y-10.f, w, h, 10.0f); gfx_quads_end(); // render goals //y = ystart+h-54; if(gameclient.snap.gameobj && gameclient.snap.gameobj->time_limit) { char buf[64]; str_format(buf, sizeof(buf), "Time Limit: %d min", gameclient.snap.gameobj->time_limit); gfx_text(0, x+w/2, y, 24.0f, buf, -1); } if(gameclient.snap.gameobj && gameclient.snap.gameobj->score_limit) { char buf[64]; str_format(buf, sizeof(buf), "Score Limit: %d", gameclient.snap.gameobj->score_limit); gfx_text(0, x+40, y, 24.0f, buf, -1); } } void SCOREBOARD::render_spectators(float x, float y, float w) { char buffer[1024*4]; int count = 0; float h = 120.0f; str_copy(buffer, "Spectators: ", sizeof(buffer)); gfx_blend_normal(); gfx_texture_set(-1); gfx_quads_begin(); gfx_setcolor(0,0,0,0.5f); draw_round_rect(x-10.f, y-10.f, w, h, 10.0f); gfx_quads_end(); for(int i = 0; i < snap_num_items(SNAP_CURRENT); i++) { SNAP_ITEM item; const void *data = snap_get_item(SNAP_CURRENT, i, &item); if(item.type == NETOBJTYPE_PLAYER_INFO) { const NETOBJ_PLAYER_INFO *info = (const NETOBJ_PLAYER_INFO *)data; if(info->team == -1) { if(count) strcat(buffer, ", "); strcat(buffer, gameclient.clients[info->cid].name); count++; } } } gfx_text(0, x+10, y, 32, buffer, (int)w-20); } void SCOREBOARD::render_scoreboard(float x, float y, float w, int team, const char *title) { //float ystart = y; float h = 750.0f; gfx_blend_normal(); gfx_texture_set(-1); gfx_quads_begin(); gfx_setcolor(0,0,0,0.5f); draw_round_rect(x-10.f, y-10.f, w, h, 40.0f); gfx_quads_end(); // render title if(!title) { if(gameclient.snap.gameobj->game_over) title = "Game Over"; else title = "Score Board"; } float tw = gfx_text_width(0, 48, title, -1); if(team == -1) { gfx_text(0, x+w/2-tw/2, y, 48, title, -1); } else { gfx_text(0, x+10, y, 48, title, -1); if(gameclient.snap.gameobj) { char buf[128]; int score = team ? gameclient.snap.gameobj->teamscore_blue : gameclient.snap.gameobj->teamscore_red; str_format(buf, sizeof(buf), "%d", score); tw = gfx_text_width(0, 48, buf, -1); gfx_text(0, x+w-tw-30, y, 48, buf, -1); } } y += 54.0f; // find players const NETOBJ_PLAYER_INFO *players[MAX_CLIENTS] = {0}; int num_players = 0; for(int i = 0; i < snap_num_items(SNAP_CURRENT); i++) { SNAP_ITEM item; const void *data = snap_get_item(SNAP_CURRENT, i, &item); if(item.type == NETOBJTYPE_PLAYER_INFO) { players[num_players] = (const NETOBJ_PLAYER_INFO *)data; num_players++; } } // sort players for(int k = 0; k < num_players; k++) // ffs, bubblesort { for(int i = 0; i < num_players-k-1; i++) { if(players[i]->score < players[i+1]->score) { const NETOBJ_PLAYER_INFO *tmp = players[i]; players[i] = players[i+1]; players[i+1] = tmp; } } } // render headlines gfx_text(0, x+10, y, 24.0f, "Score", -1); gfx_text(0, x+125, y, 24.0f, "Name", -1); gfx_text(0, x+w-70, y, 24.0f, "Ping", -1); y += 29.0f; // render player scores for(int i = 0; i < num_players; i++) { const NETOBJ_PLAYER_INFO *info = players[i]; // make sure that we render the correct team if(team == -1 || info->team != team) continue; char buf[128]; float font_size = 35.0f; if(info->local) { // background so it's easy to find the local player gfx_texture_set(-1); gfx_quads_begin(); gfx_setcolor(1,1,1,0.25f); draw_round_rect(x, y, w-20, 48, 20.0f); gfx_quads_end(); } str_format(buf, sizeof(buf), "%4d", info->score); gfx_text(0, x+60-gfx_text_width(0, font_size,buf,-1), y, font_size, buf, -1); gfx_text(0, x+128, y, font_size, gameclient.clients[info->cid].name, -1); str_format(buf, sizeof(buf), "%4d", info->latency); float tw = gfx_text_width(0, font_size, buf, -1); gfx_text(0, x+w-tw-35, y, font_size, buf, -1); // render avatar if((gameclient.snap.flags[0] && gameclient.snap.flags[0]->carried_by == info->cid) || (gameclient.snap.flags[1] && gameclient.snap.flags[1]->carried_by == info->cid)) { gfx_blend_normal(); gfx_texture_set(data->images[IMAGE_GAME].id); gfx_quads_begin(); if(info->team == 0) select_sprite(SPRITE_FLAG_BLUE, SPRITE_FLAG_FLIP_X); else select_sprite(SPRITE_FLAG_RED, SPRITE_FLAG_FLIP_X); float size = 64.0f; gfx_quads_drawTL(x+55, y-15, size/2, size); gfx_quads_end(); } render_tee(ANIMSTATE::get_idle(), &gameclient.clients[info->cid].render_info, EMOTE_NORMAL, vec2(1,0), vec2(x+90, y+28)); y += 50.0f; } } void SCOREBOARD::on_render() { if(!active) return; // TODO: repair me /* bool do_scoreboard = false; // if we are dead if(!spectate && (!gameclient.snap.local_character || gameclient.snap.local_character->health < 0)) do_scoreboard = true; // if we the game is over if(gameclient.snap.gameobj && gameclient.snap.gameobj->game_over) do_scoreboard = true;*/ float width = 400*3.0f*gfx_screenaspect(); float height = 400*3.0f; gfx_mapscreen(0, 0, width, height); float w = 650.0f; if(gameclient.snap.gameobj && !(gameclient.snap.gameobj->flags&GAMEFLAG_TEAMS)) { render_scoreboard(width/2-w/2, 150.0f, w, 0, 0); //render_scoreboard(gameobj, 0, 0, -1, 0); } else { if(gameclient.snap.gameobj && gameclient.snap.gameobj->game_over) { const char *text = "DRAW!"; if(gameclient.snap.gameobj->teamscore_red > gameclient.snap.gameobj->teamscore_blue) text = "Red Team Wins!"; else if(gameclient.snap.gameobj->teamscore_blue > gameclient.snap.gameobj->teamscore_red) text = "Blue Team Wins!"; float w = gfx_text_width(0, 92.0f, text, -1); gfx_text(0, width/2-w/2, 45, 92.0f, text, -1); } render_scoreboard(width/2-w-20, 150.0f, w, 0, "Red Team"); render_scoreboard(width/2 + 20, 150.0f, w, 1, "Blue Team"); } render_goals(width/2-w/2, 150+750+25, w); render_spectators(width/2-w/2, 150+750+25+50+25, w); }