222 lines
6.3 KiB
C++
222 lines
6.3 KiB
C++
// creation of scoreboard
|
|
#include "game.h"
|
|
|
|
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);
|
|
VARP(hidefrags, 0, 1, 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<gameent *> &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<int> &best)
|
|
{
|
|
if(cmode && cmode->hidefrags())
|
|
{
|
|
vector<teamscore> 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<gameent *> 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<gameent *> &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() && 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 + 999, 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); }
|
|
}
|
|
|