// creation of scoreboard #include "game.hh" namespace game { VARP(showservinfo, 0, 1, 1); VARP(showclientnum, 0, 0, 1); VARP(showpj, 0, 0, 1); VARP(showping, 0, 1, 1); VARP(showspectators, 0, 1, 1); VARP(highlightscore, 0, 1, 1); VARP(showconnecting, 0, 0, 1); static teaminfo teaminfos[MAXTEAMS]; void clearteaminfo() { loopi(MAXTEAMS) teaminfos[i].reset(); } void setteaminfo(int team, int frags) { if(!validteam(team)) return; teaminfo &t = teaminfos[team-1]; t.frags = frags; } static inline bool playersort(const gameent *a, const gameent *b) { if(a->state==CS_SPECTATOR) { if(b->state==CS_SPECTATOR) return strcmp(a->name, b->name) < 0; else return false; } else if(b->state==CS_SPECTATOR) return true; if(m_ctf) { if(a->flags > b->flags) return true; if(a->flags < b->flags) return false; } if(a->frags > b->frags) return true; if(a->frags < b->frags) return false; return strcmp(a->name, b->name) < 0; } void getbestplayers(vector &best) { loopv(players) { gameent *o = players[i]; if(o->state!=CS_SPECTATOR) best.add(o); } best.sort(playersort); while(best.length() > 1 && best.last()->frags < best[0]->frags) best.drop(); } void getbestteams(vector &best) { if(cmode && cmode->hidefrags()) { vector teamscores; cmode->getteamscores(teamscores); teamscores.sort(teamscore::compare); while(teamscores.length() > 1 && teamscores.last().score < teamscores[0].score) teamscores.drop(); loopv(teamscores) best.add(teamscores[i].team); } else { int bestfrags = INT_MIN; loopi(MAXTEAMS) { teaminfo &t = teaminfos[i]; bestfrags = max(bestfrags, t.frags); } loopi(MAXTEAMS) { teaminfo &t = teaminfos[i]; if(t.frags >= bestfrags) best.add(1+i); } } } static vector teamplayers[1+MAXTEAMS], spectators; static void groupplayers() { loopi(1+MAXTEAMS) teamplayers[i].setsize(0); spectators.setsize(0); loopv(players) { gameent *o = players[i]; if(!showconnecting && !o->name[0]) continue; if(o->state==CS_SPECTATOR) { spectators.add(o); continue; } int team = m_teammode && validteam(o->team) ? o->team : 0; teamplayers[team].add(o); } loopi(1+MAXTEAMS) teamplayers[i].sort(playersort); spectators.sort(playersort); } void removegroupedplayer(gameent *d) { loopi(1+MAXTEAMS) teamplayers[i].removeobj(d); spectators.removeobj(d); } void refreshscoreboard() { groupplayers(); } COMMAND(refreshscoreboard, ""); ICOMMAND(numscoreboard, "i", (int *team), intret(*team < 0 ? spectators.length() : (*team <= MAXTEAMS ? teamplayers[*team].length() : 0))); ICOMMAND(loopscoreboard, "rie", (ident *id, int *team, uint *body), { if(*team > MAXTEAMS) return; loopstart(id, stack); vector &p = *team < 0 ? spectators : teamplayers[*team]; loopv(p) { loopiter(id, stack, p[i]->clientnum); execute(body); } loopend(id, stack); }); ICOMMAND(scoreboardstatus, "i", (int *cn), { gameent *d = getclient(*cn); if(d) { int status = d->state!=CS_DEAD ? 0xFFFFFF : 0x606060; if(d->privilege) { status = d->privilege>=PRIV_ADMIN ? 0xFF8000 : 0x40FF80; if(d->state==CS_DEAD) status = (status>>1)&0x7F7F7F; } intret(status); } }); ICOMMAND(scoreboardpj, "i", (int *cn), { gameent *d = getclient(*cn); if(d && d != player1) { if(d->state==CS_LAGGED) result("LAG"); else intret(d->plag); } }); ICOMMAND(scoreboardping, "i", (int *cn), { gameent *d = getclient(*cn); if(d) { if(!showpj && d->state==CS_LAGGED) result("LAG"); else intret(d->ping); } }); ICOMMAND(scoreboardshowfrags, "", (), intret(cmode && cmode->hidefrags() ? 0 : 1)); ICOMMAND(scoreboardshowclientnum, "", (), intret(showclientnum || player1->privilege>=PRIV_MASTER ? 1 : 0)); ICOMMAND(scoreboardmultiplayer, "", (), intret(multiplayer(false) || demoplayback ? 1 : 0)); ICOMMAND(scoreboardhighlight, "i", (int *cn), intret(*cn == player1->clientnum && highlightscore && (multiplayer(false) || demoplayback || players.length() > 1) ? 0x808080 : 0)); ICOMMAND(scoreboardservinfo, "", (), { if(!showservinfo) return; const ENetAddress *address = connectedpeer(); if(address && player1->clientnum >= 0) { if(servdesc[0]) result(servdesc); else { string hostname; if(enet_address_get_host_ip(address, hostname, sizeof(hostname)) >= 0) result(tempformatstring("%s:%d", hostname, address->port)); } } }); ICOMMAND(scoreboardmode, "", (), { result(server::modeprettyname(gamemode)); }); ICOMMAND(scoreboardmap, "", (), { const char *mname = getclientmap(); result(mname[0] ? mname : "[new map]"); }); ICOMMAND(scoreboardtime, "", (), { if(m_timed && getclientmap() && (maplimit >= 0 || intermission)) { if(intermission) result("intermission"); else { int secs = max(maplimit-lastmillis, 0)/1000; result(tempformatstring("%d:%02d", secs/60, secs%60)); } } }); ICOMMAND(getteamscore, "i", (int *team), { if(m_teammode && validteam(*team)) { if(cmode && cmode->hidefrags()) intret(cmode->getteamscore(*team)); else intret(teaminfos[*team-1].frags); } }); void showscores(bool on) { UI::holdui("scoreboard", on); } }