1
0
Fork 0
forked from fte/fteqw

Added bugs relating to scr_scoreboard_* cvars, broken indepphysics, and generally screwed up

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@2547 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2007-07-23 18:52:11 +00:00
parent 3ca64edd06
commit 5fc1d3fdea
8 changed files with 484 additions and 141 deletions

View file

@ -1016,6 +1016,10 @@ unsigned long _stdcall CL_IndepPhysicsThread(void *param)
spare = CL_FilterTime((time - lasttime)*1000, cl_netfps.value); spare = CL_FilterTime((time - lasttime)*1000, cl_netfps.value);
if (spare) if (spare)
{ {
//don't let them bank too much and get sudden bursts
if (spare > 15)
spare = 15;
time -= spare/1000.0f; time -= spare/1000.0f;
EnterCriticalSection(&indepcriticialsection); EnterCriticalSection(&indepcriticialsection);
if (cls.state) if (cls.state)
@ -1073,6 +1077,99 @@ void CL_UseIndepPhysics(qboolean allow)
runningindepphys = false; runningindepphys = false;
} }
} }
#elif defined(__linux__)
#include <pthread.h>
pthread_mutex_t indepcriticalsection;
pthread_t indepphysicsthread;
void CL_AllowIndependantSendCmd(qboolean allow)
{
if (!runningindepphys)
return;
if (allowindepphys != allow && runningindepphys)
{
if (allow)
pthread_mutex_unlock(&indepcriticalsection);
else
pthread_mutex_lock(&indepcriticalsection);
allowindepphys = allow;
}
}
void *CL_IndepPhysicsThread(void *param)
{
int sleeptime;
double fps;
double time, lasttime;
double spare;
lasttime = Sys_DoubleTime();
while(runningindepphys)
{
time = Sys_DoubleTime();
spare = CL_FilterTime((time - lasttime)*1000, cl_netfps.value);
if (spare)
{
//don't let them bank too much and get sudden bursts
if (spare > 15)
spare = 15;
time -= spare/1000.0f;
pthread_mutex_lock(&indepcriticalsection);
if (cls.state)
CL_SendCmd(time - lasttime);
lasttime = time;
pthread_mutex_unlock(&indepcriticalsection);
}
fps = cl_netfps.value;
if (fps < 4)
fps = 4;
while (fps < 100)
fps*=2;
sleeptime = (1000*1000)/fps;
if (sleeptime)
usleep(sleeptime);
else
usleep(1);
}
return NULL;
}
void CL_UseIndepPhysics(qboolean allow)
{
if (runningindepphys == allow)
return;
if (allow)
{ //enable it
pthread_mutex_init(&indepcriticalsection, NULL);
runningindepphys = true;
pthread_create(&indepphysicsthread, NULL, CL_IndepPhysicsThread, NULL);
allowindepphys = 1;
//now this would be awesome, but would require root permissions... which is plain wrong!
//however, lack of this line means its really duel-core only.
//pthread_setschedparam(indepthread, SCHED_*, ?);
//is there anything to weight the thread up a bit against the main thread? (considering that most of the time we'll be idling)
}
else
{
//shut it down.
runningindepphys = false; //tell thread to exit gracefully
pthread_mutex_lock(&indepcriticalsection);
pthread_join(indepphysicsthread, 0);
pthread_mutex_unlock(&indepcriticalsection);
pthread_mutex_destroy(&indepcriticalsection);
}
}
#else #else
void CL_AllowIndependantSendCmd(qboolean allow) void CL_AllowIndependantSendCmd(qboolean allow)
{ {

View file

@ -2390,8 +2390,8 @@ void CLQ2_ParseClientinfo(int i, char *s)
Info_SetValueForKey(player->userinfo, "name", name, MAX_INFO_STRING); Info_SetValueForKey(player->userinfo, "name", name, MAX_INFO_STRING);
cl.players[i].userid = i; cl.players[i].userid = i;
cl.players[i].bottomcolor = 1; cl.players[i].rbottomcolor = 1;
cl.players[i].topcolor = 1; cl.players[i].rtopcolor = 1;
CL_ProcessUserInfo (i, player); CL_ProcessUserInfo (i, player);
} }
@ -2915,12 +2915,8 @@ CL_NewTranslation
*/ */
void CL_NewTranslation (int slot) void CL_NewTranslation (int slot)
{ {
#ifdef SWQUAKE
//int i, j; //unreferenced
int top, bottom; int top, bottom;
//qbyte *dest, *source; //unreferenced
int local; int local;
#endif
char *s; char *s;
player_info_t *player; player_info_t *player;
@ -2936,58 +2932,56 @@ void CL_NewTranslation (int slot)
player->skin = NULL; player->skin = NULL;
#ifdef RGLQUAKE
if (qrenderer == QR_OPENGL) top = player->rtopcolor;
{ //gl doesn't need to do anything except prevent the sys_error below. bottom = player->rbottomcolor;
return; if (cl.splitclients < 2 && !(cl.fpd & FPD_NO_FORCE_COLOR)) //no colour/skin forcing in splitscreen.
{
if (cl.teamplay && cl.spectator)
{
local = Cam_TrackNum(0);
if (local < 0)
local = cl.playernum[0];
}
else
local = cl.playernum[0];
if (cl.teamplay && !strcmp(player->team, cl.players[local].team))
{
if (cl_teamtopcolor>=0)
top = cl_teamtopcolor;
if (cl_teambottomcolor>=0)
bottom = cl_teambottomcolor;
}
else
{
if (cl_enemytopcolor>=0)
top = cl_enemytopcolor;
if (cl_enemybottomcolor>=0)
bottom = cl_enemybottomcolor;
}
} }
#endif
if (top > 13 || top < 0)
top = 13;
if (bottom > 13 || bottom < 0)
bottom = 13;
#ifdef SWQUAKE #ifdef SWQUAKE
if (qrenderer == QR_SOFTWARE) if (qrenderer == QR_SOFTWARE)
{ {
top = player->topcolor; if (player->ttopcolor != top || player->tbottomcolor != bottom || !player->skin)
bottom = player->bottomcolor;
if (!cl.splitclients && !(cl.fpd & FPD_NO_FORCE_COLOR)) //no colour/skin forcing in splitscreen.
{ {
if (cl.teamplay && cl.spectator) player->ttopcolor = top;
{ player->tbottomcolor = bottom;
local = Cam_TrackNum(0);
if (local < 0)
local = cl.playernum[0];
}
else
local = cl.playernum[0];
if (cl.teamplay && !strcmp(player->team, cl.players[local].team))
{
if (cl_teamtopcolor>=0)
top = cl_teamtopcolor;
if (cl_teambottomcolor>=0)
bottom = cl_teambottomcolor;
}
else
{
if (cl_enemytopcolor>=0)
top = cl_enemytopcolor;
if (cl_enemybottomcolor>=0)
bottom = cl_enemybottomcolor;
}
}
if (top > 13 || top < 0)
top = 13;
if (bottom > 13 || bottom < 0)
bottom = 13;
if (player->_topcolor != top ||
player->_bottomcolor != bottom || !player->skin) {
player->_topcolor = top;
player->_bottomcolor = bottom;
D_DereferenceRemap(player->palremap); D_DereferenceRemap(player->palremap);
player->palremap = D_GetPaletteRemap(255, 255, 255, false, true, top, bottom); player->palremap = D_GetPaletteRemap(255, 255, 255, false, true, top, bottom);
} }
return; return;
} }
#endif #endif
//other renderers still need the team stuff set, but that's all
player->ttopcolor = top;
player->tbottomcolor = bottom;
} }
/* /*
@ -2999,8 +2993,8 @@ void CL_ProcessUserInfo (int slot, player_info_t *player)
{ {
Q_strncpyz (player->name, Info_ValueForKey (player->userinfo, "name"), sizeof(player->name)); Q_strncpyz (player->name, Info_ValueForKey (player->userinfo, "name"), sizeof(player->name));
Q_strncpyz (player->team, Info_ValueForKey (player->userinfo, "team"), sizeof(player->team)); Q_strncpyz (player->team, Info_ValueForKey (player->userinfo, "team"), sizeof(player->team));
player->topcolor = atoi(Info_ValueForKey (player->userinfo, "topcolor")); player->rtopcolor = atoi(Info_ValueForKey (player->userinfo, "topcolor"));
player->bottomcolor = atoi(Info_ValueForKey (player->userinfo, "bottomcolor")); player->rbottomcolor = atoi(Info_ValueForKey (player->userinfo, "bottomcolor"));
if (atoi(Info_ValueForKey (player->userinfo, "*spectator"))) if (atoi(Info_ValueForKey (player->userinfo, "*spectator")))
player->spectator = true; player->spectator = true;
else else
@ -3590,7 +3584,7 @@ int CL_PlayerColor(player_info_t *plr, int *name_ormask)
if (cl.teamfortress) //override based on team if (cl.teamfortress) //override based on team
{ {
// TODO: needs some work // TODO: needs some work
switch (plr->bottomcolor) switch (plr->rbottomcolor)
{ //translate q1 skin colours to console colours { //translate q1 skin colours to console colours
case 10: case 10:
case 1: case 1:
@ -4986,8 +4980,8 @@ void CLNQ_ParseServerMessage (void)
break; break;
//FIXME:!!!! //FIXME:!!!!
cl.players[i].topcolor = a&0x0f; cl.players[i].rtopcolor = a&0x0f;
cl.players[i].bottomcolor = (a&0xf0)>>4; cl.players[i].rbottomcolor = (a&0xf0)>>4;
if (cls.state == ca_active) if (cls.state == ca_active)
Skin_Find (&cl.players[i]); Skin_Find (&cl.players[i]);

View file

@ -382,13 +382,13 @@ int VARGS Plug_GetPlayerInfo(void *offset, unsigned int mask, const long *arg)
return 0; return 0;
} }
} }
out->bottomcolour = cl.players[i].bottomcolor; out->bottomcolour = cl.players[i].rbottomcolor;
out->topcolour = cl.players[i].rtopcolor;
out->frags = cl.players[i].frags; out->frags = cl.players[i].frags;
Q_strncpyz(out->name, cl.players[i].name, PLUGMAX_SCOREBOARDNAME); Q_strncpyz(out->name, cl.players[i].name, PLUGMAX_SCOREBOARDNAME);
out->ping = cl.players[i].ping; out->ping = cl.players[i].ping;
out->pl = cl.players[i].pl; out->pl = cl.players[i].pl;
out->starttime = cl.players[i].entertime; out->starttime = cl.players[i].entertime;
out->topcolour = cl.players[i].topcolor;
out->userid = cl.players[i].userid; out->userid = cl.players[i].userid;
out->spectator = cl.players[i].spectator; out->spectator = cl.players[i].spectator;
Q_strncpyz(out->userinfo, cl.players[i].userinfo, sizeof(out->userinfo)); Q_strncpyz(out->userinfo, cl.players[i].userinfo, sizeof(out->userinfo));

View file

@ -1439,13 +1439,13 @@ long UI_SystemCallsEx(void *offset, unsigned int mask, int fn, const long *arg)
return 0; return 0;
} }
} }
vci->bottomcolour = cl.players[i].bottomcolor; vci->bottomcolour = cl.players[i].rbottomcolor;
vci->frags = cl.players[i].frags; vci->frags = cl.players[i].frags;
Q_strncpyz(vci->name, cl.players[i].name, UIMAX_SCOREBOARDNAME); Q_strncpyz(vci->name, cl.players[i].name, UIMAX_SCOREBOARDNAME);
vci->ping = cl.players[i].ping; vci->ping = cl.players[i].ping;
vci->pl = cl.players[i].pl; vci->pl = cl.players[i].pl;
vci->starttime = cl.players[i].entertime; vci->starttime = cl.players[i].entertime;
vci->topcolour = cl.players[i].topcolor; vci->topcolour = cl.players[i].rtopcolor;
vci->userid = cl.players[i].userid; vci->userid = cl.players[i].userid;
Q_strncpyz(vci->userinfo, cl.players[i].userinfo, sizeof(vci->userinfo)); Q_strncpyz(vci->userinfo, cl.players[i].userinfo, sizeof(vci->userinfo));
} }

View file

@ -144,11 +144,11 @@ typedef struct player_info_s
qboolean ignored; qboolean ignored;
// skin information // skin information
int topcolor; int rtopcolor; //real, according to their userinfo
int bottomcolor; int rbottomcolor;
int _topcolor; int ttopcolor; //team, according to colour forcing
int _bottomcolor; int tbottomcolor;
#ifdef SWQUAKE #ifdef SWQUAKE
struct palremap_s *palremap; struct palremap_s *palremap;

View file

@ -17,6 +17,7 @@ cvar_t r_dodgypcxfiles = SCVAR("r_dodgypcxfiles", "0"); //Quake 2's PCX loading
//and some Q2 mods include PCX files //and some Q2 mods include PCX files
//that only work with this assumption //that only work with this assumption
#define GLOBAL(x) x
#ifndef _WIN32 #ifndef _WIN32
#include <unistd.h> #include <unistd.h>
#endif #endif
@ -874,6 +875,8 @@ term_source (j_decompress_ptr cinfo)
} }
#define GLOBAL(x) x
GLOBAL(void) GLOBAL(void)
jpeg_mem_src (j_decompress_ptr cinfo, qbyte * infile, int maxlen) jpeg_mem_src (j_decompress_ptr cinfo, qbyte * infile, int maxlen)
{ {

View file

@ -23,6 +23,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
extern cvar_t hud_tracking_show; extern cvar_t hud_tracking_show;
cvar_t scr_scoreboard_drawtitle = SCVAR("scr_scoreboard_drawtitle", "1");
cvar_t scr_scoreboard_showfrags = SCVAR("scr_scoreboard_showfrags", "0");
cvar_t scr_scoreboard_titleseperator = SCVAR("scr_scoreboard_titleseperator", "1");
cvar_t scr_scoreboard_forcecolors = SCVAR("scr_scoreboard_forcecolors", "0"); //damn americans
//=========================================== //===========================================
//rogue changed and added defines //rogue changed and added defines
@ -108,6 +113,31 @@ void Sbar_TeamOverlay (void);
void Sbar_MiniDeathmatchOverlay (void); void Sbar_MiniDeathmatchOverlay (void);
void Sbar_ChatModeOverlay(void); void Sbar_ChatModeOverlay(void);
int Sbar_PlayerNum(void)
{
int num;
num = cl.spectator?Cam_TrackNum(0):-1;
if (num < 0)
num = cl.playernum;
return num;
}
int Sbar_TopColour(player_info_t *p)
{
if (scr_scoreboard_forcecolors.value)
return p->ttopcolor;
else
return p->rtopcolor;
}
int Sbar_BottomColour(player_info_t *p)
{
if (scr_scoreboard_forcecolors.value)
return p->tbottomcolor;
else
return p->rbottomcolor;
}
void Draw_FunString(int x, int y, unsigned char *str) void Draw_FunString(int x, int y, unsigned char *str)
{ {
int ext = CON_WHITEMASK; int ext = CON_WHITEMASK;
@ -954,6 +984,11 @@ void Sbar_Start (void) //if one of these fails, skip the entire status bar.
void Sbar_Init (void) void Sbar_Init (void)
{ {
Cvar_Register(&scr_scoreboard_drawtitle, "Scoreboard settings");
Cvar_Register(&scr_scoreboard_showfrags, "Scoreboard settings");
Cvar_Register(&scr_scoreboard_titleseperator, "Scoreboard settings");
Cvar_Register(&scr_scoreboard_forcecolors, "Scoreboard settings");
Cmd_AddCommand ("+showscores", Sbar_ShowScores); Cmd_AddCommand ("+showscores", Sbar_ShowScores);
Cmd_AddCommand ("-showscores", Sbar_DontShowScores); Cmd_AddCommand ("-showscores", Sbar_DontShowScores);
@ -1115,8 +1150,6 @@ void Sbar_DrawNum (int x, int y, int num, int digits, int color)
//============================================================================= //=============================================================================
//ZOID: this should be MAX_CLIENTS, not MAX_SCOREBOARD!!
//int fragsort[MAX_SCOREBOARD];
int fragsort[MAX_CLIENTS]; int fragsort[MAX_CLIENTS];
int scoreboardlines; int scoreboardlines;
typedef struct { typedef struct {
@ -1124,6 +1157,8 @@ typedef struct {
int frags; int frags;
int players; int players;
int plow, phigh, ptotal; int plow, phigh, ptotal;
int topcolour, bottomcolour;
qboolean ownteam;
} team_t; } team_t;
team_t teams[MAX_CLIENTS]; team_t teams[MAX_CLIENTS];
int teamsort[MAX_CLIENTS]; int teamsort[MAX_CLIENTS];
@ -1167,6 +1202,7 @@ void Sbar_SortTeams (void)
int i, j, k; int i, j, k;
player_info_t *s; player_info_t *s;
char t[16+1]; char t[16+1];
int ownnum;
// request new ping times every two second // request new ping times every two second
scoreboardteams = 0; scoreboardteams = 0;
@ -1179,36 +1215,49 @@ void Sbar_SortTeams (void)
for (i = 0; i < MAX_CLIENTS; i++) for (i = 0; i < MAX_CLIENTS; i++)
teams[i].plow = 999; teams[i].plow = 999;
for (i = 0; i < MAX_CLIENTS; i++) { ownnum = Sbar_PlayerNum();
for (i = 0; i < MAX_CLIENTS; i++)
{
s = &cl.players[i]; s = &cl.players[i];
if (!s->name[0]) if (!s->name[0] || s->spectator)
continue;
if (s->spectator)
continue; continue;
// find his team in the list // find his team in the list
t[16] = 0;
Q_strncpyz(t, s->team, sizeof(t)); Q_strncpyz(t, s->team, sizeof(t));
if (!t[0]) if (!t[0])
continue; // not on team continue; // not on team
for (j = 0; j < scoreboardteams; j++) for (j = 0; j < scoreboardteams; j++)
if (!strcmp(teams[j].team, t)) { if (!strcmp(teams[j].team, t))
teams[j].frags += s->frags; {
teams[j].players++; break;
goto addpinginfo;
} }
if (j == scoreboardteams) { // must add him
j = scoreboardteams++; /*if (cl.teamfortress)
strcpy(teams[j].team, t); {
teams[j].frags = s->frags; teams[j].topcolour = teams[j].bottomcolour = TF_TeamToColour(t);
teams[j].players = 1;
addpinginfo:
if (teams[j].plow > s->ping)
teams[j].plow = s->ping;
if (teams[j].phigh < s->ping)
teams[j].phigh = s->ping;
teams[j].ptotal += s->ping;
} }
else*/ if (j == scoreboardteams || i == ownnum)
{
teams[j].topcolour = Sbar_TopColour(s);
teams[j].bottomcolour = Sbar_BottomColour(s);
}
if (j == scoreboardteams)
{ // create a team for this player
scoreboardteams++;
strcpy(teams[j].team, t);
}
teams[j].frags += s->frags;
teams[j].players++;
if (teams[j].plow > s->ping)
teams[j].plow = s->ping;
if (teams[j].phigh < s->ping)
teams[j].phigh = s->ping;
teams[j].ptotal += s->ping;
} }
// sort // sort
@ -1218,7 +1267,8 @@ addpinginfo:
// good 'ol bubble sort // good 'ol bubble sort
for (i = 0; i < scoreboardteams - 1; i++) for (i = 0; i < scoreboardteams - 1; i++)
for (j = i + 1; j < scoreboardteams; j++) for (j = i + 1; j < scoreboardteams; j++)
if (teams[teamsort[i]].frags < teams[teamsort[j]].frags) { if (teams[teamsort[i]].frags < teams[teamsort[j]].frags)
{
k = teamsort[i]; k = teamsort[i];
teamsort[i] = teamsort[j]; teamsort[i] = teamsort[j];
teamsort[j] = k; teamsort[j] = k;
@ -1468,11 +1518,14 @@ void Sbar_DrawFrags (void)
int i, k, l; int i, k, l;
int top, bottom; int top, bottom;
int x, y, f; int x, y, f;
int ownnum;
char num[12]; char num[12];
player_info_t *s; player_info_t *s;
Sbar_SortFrags (false); Sbar_SortFrags (false);
ownnum = Sbar_PlayerNum();
// draw the text // draw the text
l = scoreboardlines <= 4 ? scoreboardlines : 4; l = scoreboardlines <= 4 ? scoreboardlines : 4;
@ -1490,8 +1543,8 @@ void Sbar_DrawFrags (void)
continue; continue;
// draw background // draw background
top = s->topcolor; top = Sbar_TopColour(s);
bottom = s->bottomcolor; bottom = Sbar_BottomColour(s);
top = (top < 0) ? 0 : ((top > 13) ? 13 : top); top = (top < 0) ? 0 : ((top > 13) ? 13 : top);
bottom = (bottom < 0) ? 0 : ((bottom > 13) ? 13 : bottom); bottom = (bottom < 0) ? 0 : ((bottom > 13) ? 13 : bottom);
@ -1511,7 +1564,7 @@ void Sbar_DrawFrags (void)
Sbar_DrawCharacter ( (x+2)*8 , -24, num[1]); Sbar_DrawCharacter ( (x+2)*8 , -24, num[1]);
Sbar_DrawCharacter ( (x+3)*8 , -24, num[2]); Sbar_DrawCharacter ( (x+3)*8 , -24, num[2]);
if (k == cl.playernum[0]) if (k == ownnum)
{ {
Sbar_DrawCharacter (x*8+2, -24, 16); Sbar_DrawCharacter (x*8+2, -24, 16);
Sbar_DrawCharacter ( (x+4)*8-4, -24, 17); Sbar_DrawCharacter ( (x+4)*8-4, -24, 17);
@ -1942,11 +1995,16 @@ void Sbar_TeamOverlay (void)
scr_copyeverything = 1; scr_copyeverything = 1;
scr_fullupdate = 0; scr_fullupdate = 0;
pic = Draw_SafeCachePic ("gfx/ranking.lmp"); y = 0;
if (pic)
Draw_Pic ((vid.width-pic->width)/2, 0, pic); if (scr_scoreboard_drawtitle.value)
{
pic = Draw_SafeCachePic ("gfx/ranking.lmp");
if (pic)
Draw_Pic ((vid.width-pic->width)/2, 0, pic);
y += 24;
}
y = 24;
x = (vid.width - 320)/2 + 36; x = (vid.width - 320)/2 + 36;
Draw_String(x, y, "low/avg/high team total players"); Draw_String(x, y, "low/avg/high team total players");
y += 8; y += 8;
@ -2012,6 +2070,83 @@ Sbar_DeathmatchOverlay
ping time frags name ping time frags name
================== ==================
*/ */
//for reference:
//define COLUMN(title, width, code)
#define COLUMN_PING COLUMN(ping, 4*8, \
{ \
int p = s->ping; \
if (p < 0 || p > 999) p = 999; \
sprintf(num, "%4i", p); \
Draw_FunString(x, y, num); \
})
#define COLUMN_PL COLUMN(pl, 2*8, \
{ \
int p = s->pl; \
sprintf(num, "%3i", p); \
Draw_FunString(x, y, num); \
})
#define COLUMN_TIME COLUMN(time, 4*8, \
{ \
if (cl.intermission) \
total = cl.completed_time - s->entertime; \
else \
total = cl.servertime - s->entertime; \
minutes = (int)total/60; \
sprintf (num, "%4i", minutes); \
Draw_String ( x , y, num); \
})
#define COLUMN_FRAGS COLUMN(frags, 5*8, \
{ \
top = Sbar_TopColour(s); \
bottom = Sbar_BottomColour(s); \
top = Sbar_ColorForMap (top); \
bottom = Sbar_ColorForMap (bottom); \
\
if (largegame) \
Draw_Fill ( x, y+1, 40, 3, top); \
else \
Draw_Fill ( x, y, 40, 4, top); \
Draw_Fill ( x, y+4, 40, 4, bottom); \
\
f = s->frags; \
sprintf (num, "%3i",f); \
\
Draw_Character ( x+8 , y, num[0]); \
Draw_Character ( x+16 , y, num[1]); \
Draw_Character ( x+24 , y, num[2]); \
\
if ((cl.spectator && k == spec_track[0]) || \
(!cl.spectator && k == cl.playernum[0])) \
{ \
Draw_Character ( x, y, 16); \
Draw_Character ( x + 32, y, 17); \
} \
})
#define COLUMN_TEAMNAME COLUMN(team, 4*8, {Draw_FunStringLen(x, y, s->team, 4);})
#define COLUMN_NAME COLUMN(name, 16*8, {Draw_FunString(x, y, s->name);})
#define COLUMN_KILLS COLUMN(kils, 4*8, {Draw_FunString(x, y, va("%4i", Stats_GetKills(k)));})
#define COLUMN_TKILLS COLUMN(tkil, 4*8, {Draw_FunString(x, y, va("%4i", Stats_GetTKills(k)));})
#define COLUMN_DEATHS COLUMN(dths, 4*8, {Draw_FunString(x, y, va("%4i", Stats_GetDeaths(k)));})
#define COLUMN_TOUCHES COLUMN(tchs, 4*8, {Draw_FunString(x, y, va("%4i", Stats_GetTouches(k)));})
#define COLUMN_CAPS COLUMN(caps, 4*8, {Draw_FunString(x, y, va("%4i", Stats_GetCaptures(k)));})
//columns are listed here in display order
#define ALLCOLUMNS COLUMN_PING COLUMN_PL COLUMN_TIME COLUMN_FRAGS COLUMN_TEAMNAME COLUMN_NAME COLUMN_KILLS COLUMN_TKILLS COLUMN_DEATHS COLUMN_TOUCHES COLUMN_CAPS
enum
{
#define COLUMN(title, width, code) COLUMN##title,
ALLCOLUMNS
#undef COLUMN
COLUMN_MAX
};
#define ADDCOLUMN(id) showcolumns |= (1<<id)
void Sbar_DeathmatchOverlay (int start) void Sbar_DeathmatchOverlay (int start)
{ {
mpic_t *pic; mpic_t *pic;
@ -2024,6 +2159,8 @@ void Sbar_DeathmatchOverlay (int start)
int minutes; int minutes;
int p; int p;
int skip = 10; int skip = 10;
int showcolumns;
int startx;
if (largegame) if (largegame)
skip = 8; skip = 8;
@ -2038,11 +2175,18 @@ void Sbar_DeathmatchOverlay (int start)
scr_copyeverything = 1; scr_copyeverything = 1;
scr_fullupdate = 0; scr_fullupdate = 0;
if (!start) if (start)
y = start;
else
{ {
pic = Draw_SafeCachePic ("gfx/ranking.lmp"); y = 0;
if (pic) if (scr_scoreboard_drawtitle.value)
Draw_Pic ((vid.width - 320)/2 + 160-pic->width/2, 0, pic); {
pic = Draw_SafeCachePic ("gfx/ranking.lmp");
if (pic)
Draw_Pic ((vid.width - 320)/2 + 160-pic->width/2, 0, pic);
y += 24;
}
} }
// scores // scores
@ -2055,6 +2199,78 @@ void Sbar_DeathmatchOverlay (int start)
y = start; y = start;
else else
y = 24; y = 24;
showcolumns = 0;
//we use startx here as the total width
startx = 0;
#define COLUMN(title, cwidth, code) if (startx+(cwidth)+8 <= vid.width) {showcolumns |= (1<<COLUMN##title); startx += cwidth+8;}
//columns are listed here in priority order (if the screen is too narrow, later ones will be hidden)
COLUMN_NAME
COLUMN_PING
COLUMN_PL
COLUMN_TIME
COLUMN_FRAGS
if (cl.teamplay)
{
COLUMN_TEAMNAME
}
if (cl.teamplay && Stats_HaveFlags())
{
COLUMN_CAPS
}
if (scr_scoreboard_showfrags.value && Stats_HaveKills())
{
COLUMN_KILLS
COLUMN_DEATHS
if (cl.teamplay)
{
COLUMN_TKILLS
}
}
if (cl.teamplay && Stats_HaveFlags())
{
COLUMN_TOUCHES
}
#undef COLUMN
startx = (vid.width-startx)/2;
x = startx;
#define COLUMN(title, width, code) if (showcolumns & (1<<COLUMN##title)) {Draw_FunString(x, y, #title); x += width+8;}
ALLCOLUMNS
#undef COLUMN
y += 8;
if (scr_scoreboard_titleseperator.value)
{
x = startx;
#define COLUMN(title, width, code) if (showcolumns & (1<<COLUMN##title)) {Draw_String(x, y, "\x1d"); for (i = 8; i < width-8; i+= 8) Draw_String(x+i, y, "\x1e"); Draw_String(x+i, y, "\x1f"); x += width+8;}
ALLCOLUMNS
#undef COLUMN
y += 8;
}
y -= skip;
for (i = 0; i < scoreboardlines; i++)
{
k = fragsort[i];
s = &cl.players[k];
if (!s->name[0])
continue;
y += skip;
if (y > vid.height-10)
break;
x = startx;
#define COLUMN(title, width, code) if (showcolumns & (1<<COLUMN##title)) {code x += width+8;}
ALLCOLUMNS
#undef COLUMN
}
/*
if (cl.teamplay) if (cl.teamplay)
{ {
if (scr_chatmode) if (scr_chatmode)
@ -2165,7 +2381,7 @@ void Sbar_DeathmatchOverlay (int start)
y += skip; y += skip;
} }
*/
Draw_Character(0,0,' ' | CON_WHITEMASK); Draw_Character(0,0,' ' | CON_WHITEMASK);
if (y >= vid.height-10) // we ran over the screen size, squish if (y >= vid.height-10) // we ran over the screen size, squish
@ -2228,8 +2444,8 @@ void Sbar_ChatModeOverlay(void)
continue; continue;
// draw background // draw background
top = s->topcolor; top = Sbar_TopColour(s);
bottom = s->bottomcolor; bottom = Sbar_BottomColour(s);
top = Sbar_ColorForMap (top); top = Sbar_ColorForMap (top);
bottom = Sbar_ColorForMap (bottom); bottom = Sbar_ColorForMap (bottom);
@ -2338,8 +2554,8 @@ void Sbar_MiniDeathmatchOverlay (void)
continue; continue;
// draw ping // draw ping
top = s->topcolor; top = Sbar_TopColour(s);
bottom = s->bottomcolor; bottom = Sbar_BottomColour(s);
top = Sbar_ColorForMap (top); top = Sbar_ColorForMap (top);
bottom = Sbar_ColorForMap (bottom); bottom = Sbar_ColorForMap (bottom);

View file

@ -2445,19 +2445,19 @@ void TP_ParsePlayerInfo(player_state_t *oldstate, player_state_t *state, player_
eyes = state->modelindex && cl.model_precache[state->modelindex] && !strcmp(cl.model_precache[state->modelindex]->name, "progs/eyes.mdl"); eyes = state->modelindex && cl.model_precache[state->modelindex] && !strcmp(cl.model_precache[state->modelindex]->name, "progs/eyes.mdl");
if (state->effects & (EF_BLUE | EF_RED) || eyes) if (state->effects & (EF_BLUE | EF_RED) || eyes)
{ {
vars.enemy_powerups = 0; vars.enemy_powerups = 0;
vars.enemy_powerups_time = realtime; vars.enemy_powerups_time = realtime;
if (state->effects & EF_BLUE) if (state->effects & EF_BLUE)
vars.enemy_powerups |= TP_QUAD; vars.enemy_powerups |= TP_QUAD;
if (state->effects & EF_RED) if (state->effects & EF_RED)
vars.enemy_powerups |= TP_PENT; vars.enemy_powerups |= TP_PENT;
if (eyes) if (eyes)
vars.enemy_powerups |= TP_RING; vars.enemy_powerups |= TP_RING;
} }
} }
if (!cl.spectator && !cl.teamfortress && info - cl.players == cl.playernum[SP]) if (!cl.spectator && !cl.teamfortress && info - cl.players == cl.playernum[SP])
{ {
if ((state->effects & (QWEF_FLAG1|QWEF_FLAG2)) && !(oldstate->effects & (QWEF_FLAG1|QWEF_FLAG2))) if ((state->effects & (QWEF_FLAG1|QWEF_FLAG2)) && !(oldstate->effects & (QWEF_FLAG1|QWEF_FLAG2)))
@ -2505,9 +2505,11 @@ more:
if (FindNearestItem (it_weapons, &item)) { if (FindNearestItem (it_weapons, &item)) {
ExecTookTrigger (item->cvar->string, item->itemflag, org); ExecTookTrigger (item->cvar->string, item->itemflag, org);
} }
else { else
{
// we don't know what entity caused the sound, try to guess... // we don't know what entity caused the sound, try to guess...
if (vars.stat_framecounts[STAT_ITEMS] == cls.framecount) { if (vars.stat_framecounts[STAT_ITEMS] == cls.framecount)
{
if (vars.items & ~vars.olditems & IT_LIGHTNING) if (vars.items & ~vars.olditems & IT_LIGHTNING)
ExecTookTrigger (tp_name_lg.string, it_lg, cl.simorg[SP]); ExecTookTrigger (tp_name_lg.string, it_lg, cl.simorg[SP]);
else if (vars.items & ~vars.olditems & IT_ROCKET_LAUNCHER) else if (vars.items & ~vars.olditems & IT_ROCKET_LAUNCHER)
@ -2526,7 +2528,8 @@ more:
} }
// armor // armor
if (!strcmp(s, "items/armor1.wav")) { if (!strcmp(s, "items/armor1.wav"))
{
item_t *item; item_t *item;
qbool armor_updated; qbool armor_updated;
int armortype; int armortype;
@ -2552,7 +2555,8 @@ more:
} }
} }
static qboolean TP_IsItemVisible(item_vis_t *visitem) { static qboolean TP_IsItemVisible(item_vis_t *visitem)
{
vec3_t end, v; vec3_t end, v;
trace_t trace; trace_t trace;
@ -2602,7 +2606,8 @@ static qboolean TP_IsItemVisible(item_vis_t *visitem) {
return false; return false;
} }
static float TP_RankPoint(item_vis_t *visitem) { static float TP_RankPoint(item_vis_t *visitem)
{
vec3_t v2, v3; vec3_t v2, v3;
float miss; float miss;
@ -2620,41 +2625,50 @@ static float TP_RankPoint(item_vis_t *visitem) {
return (visitem->dist < 3000.0 / 8.0) ? miss * (visitem->dist * 8.0 * 0.0002f + 0.3f) : miss; return (visitem->dist < 3000.0 / 8.0) ? miss * (visitem->dist * 8.0 * 0.0002f + 0.3f) : miss;
} }
static char *Utils_TF_ColorToTeam_Failsafe(int color) { static char *Utils_TF_ColorToTeam_Failsafe(int color)
{
int i, j, teamcounts[8], numteamsseen = 0, best = -1; int i, j, teamcounts[8], numteamsseen = 0, best = -1;
char *teams[MAX_CLIENTS]; char *teams[MAX_CLIENTS];
memset(teams, 0, sizeof(teams)); memset(teams, 0, sizeof(teams));
memset(teamcounts, 0, sizeof(teamcounts)); memset(teamcounts, 0, sizeof(teamcounts));
for (i = 0; i < MAX_CLIENTS; i++) { for (i = 0; i < MAX_CLIENTS; i++)
{
if (!cl.players[i].name[0] || cl.players[i].spectator) if (!cl.players[i].name[0] || cl.players[i].spectator)
continue; continue;
if (cl.players[i].bottomcolor != color) if (cl.players[i].rbottomcolor != color)
continue; continue;
for (j = 0; j < numteamsseen; j++) { for (j = 0; j < numteamsseen; j++)
{
if (!strcmp(cl.players[i].team, teams[j])) if (!strcmp(cl.players[i].team, teams[j]))
break; break;
} }
if (j == numteamsseen) { if (j == numteamsseen)
{
teams[numteamsseen] = cl.players[i].team; teams[numteamsseen] = cl.players[i].team;
teamcounts[numteamsseen] = 1; teamcounts[numteamsseen] = 1;
numteamsseen++; numteamsseen++;
} else { }
else
{
teamcounts[j]++; teamcounts[j]++;
} }
} }
for (i = 0; i < numteamsseen; i++) { for (i = 0; i < numteamsseen; i++)
{
if (best == -1 || teamcounts[i] > teamcounts[best]) if (best == -1 || teamcounts[i] > teamcounts[best])
best = i; best = i;
} }
return (best == -1) ? "" : teams[best]; return (best == -1) ? "" : teams[best];
} }
char *Utils_TF_ColorToTeam(int color) { char *Utils_TF_ColorToTeam(int color)
{
char *s; char *s;
switch (color) { switch (color)
{
case 13: case 13:
if (*(s = Info_ValueForKey(cl.serverinfo, "team1")) || *(s = Info_ValueForKey(cl.serverinfo, "t1"))) if (*(s = Info_ValueForKey(cl.serverinfo, "team1")) || *(s = Info_ValueForKey(cl.serverinfo, "t1")))
return s; return s;
@ -2678,7 +2692,8 @@ char *Utils_TF_ColorToTeam(int color) {
} }
static void TP_FindPoint (void) { static void TP_FindPoint (void)
{
packet_entities_t *pak; packet_entities_t *pak;
entity_state_t *ent; entity_state_t *ent;
int i, j, pointflags_dmm; int i, j, pointflags_dmm;
@ -2703,7 +2718,8 @@ static void TP_FindPoint (void) {
visitem.vieworg[2] += 22 + (v_viewheight.value ? bound (-7, v_viewheight.value, 4) : 0); visitem.vieworg[2] += 22 + (v_viewheight.value ? bound (-7, v_viewheight.value, 4) : 0);
pointflags_dmm = pointflags; pointflags_dmm = pointflags;
if (!cl.teamfortress && cl.deathmatch >= 1 && cl.deathmatch <= 4) { if (!cl.teamfortress && cl.deathmatch >= 1 && cl.deathmatch <= 4)
{
if (cl.deathmatch == 4) if (cl.deathmatch == 4)
pointflags_dmm &= ~it_ammo; pointflags_dmm &= ~it_ammo;
if (cl.deathmatch != 1) if (cl.deathmatch != 1)
@ -2711,13 +2727,16 @@ static void TP_FindPoint (void) {
} }
pak = &cl.frames[cl.validsequence & UPDATE_MASK].packet_entities; pak = &cl.frames[cl.validsequence & UPDATE_MASK].packet_entities;
for (i = 0,ent = pak->entities; i < pak->num_entities; i++, ent++) { for (i = 0,ent = pak->entities; i < pak->num_entities; i++, ent++)
{
item = model2item[ent->modelindex]; item = model2item[ent->modelindex];
if (!item || !(item->itemflag & pointflags_dmm)) if (!item || !(item->itemflag & pointflags_dmm))
continue; continue;
// special check for armors // special check for armors
if (item->itemflag == (it_ra|it_ya|it_ga)) { if (item->itemflag == (it_ra|it_ya|it_ga))
switch (ent->skinnum) { {
switch (ent->skinnum)
{
case 0: if (!(pointflags_dmm & it_ga)) continue; case 0: if (!(pointflags_dmm & it_ga)) continue;
case 1: if (!(pointflags_dmm & it_ya)) continue; case 1: if (!(pointflags_dmm & it_ya)) continue;
default: if (!(pointflags_dmm & it_ra)) continue; default: if (!(pointflags_dmm & it_ra)) continue;
@ -2733,7 +2752,8 @@ static void TP_FindPoint (void) {
continue; continue;
// check if we can actually see the object // check if we can actually see the object
if ((rank < best || best < 0) && TP_IsItemVisible(&visitem)) { if ((rank < best || best < 0) && TP_IsItemVisible(&visitem))
{
best = rank; best = rank;
bestent = ent; bestent = ent;
bestitem = item; bestitem = item;
@ -2742,7 +2762,8 @@ static void TP_FindPoint (void) {
state = cl.frames[cl.parsecount & UPDATE_MASK].playerstate; state = cl.frames[cl.parsecount & UPDATE_MASK].playerstate;
info = cl.players; info = cl.players;
for (j = 0; j < MAX_CLIENTS; j++, info++, state++) { for (j = 0; j < MAX_CLIENTS; j++, info++, state++)
{
if (state->messagenum != cl.parsecount || j == cl.playernum[0] || info->spectator) if (state->messagenum != cl.parsecount || j == cl.playernum[0] || info->spectator)
continue; continue;
@ -2762,7 +2783,8 @@ static void TP_FindPoint (void) {
continue; continue;
// check if we can actually see the object // check if we can actually see the object
if ((rank < best || best < 0) && TP_IsItemVisible(&visitem)) { if ((rank < best || best < 0) && TP_IsItemVisible(&visitem))
{
qboolean teammate, eyes = false; qboolean teammate, eyes = false;
eyes = state->modelindex && cl.model_precache[state->modelindex] && !strcmp(cl.model_precache[state->modelindex]->name, "progs/eyes.mdl"); eyes = state->modelindex && cl.model_precache[state->modelindex] && !strcmp(cl.model_precache[state->modelindex]->name, "progs/eyes.mdl");
@ -2781,13 +2803,15 @@ static void TP_FindPoint (void) {
} }
} }
if (best >= 0 && bestinfo) { if (best >= 0 && bestinfo)
{
qboolean teammate, eyes; qboolean teammate, eyes;
char *name, buf[256] = {0}; char *name, buf[256] = {0};
eyes = beststate->modelindex && cl.model_precache[beststate->modelindex] && !strcmp(cl.model_precache[beststate->modelindex]->name, "progs/eyes.mdl"); eyes = beststate->modelindex && cl.model_precache[beststate->modelindex] && !strcmp(cl.model_precache[beststate->modelindex]->name, "progs/eyes.mdl");
if (cl.teamfortress) { if (cl.teamfortress)
teammate = !strcmp(Utils_TF_ColorToTeam(bestinfo->bottomcolor), TP_PlayerTeam()); {
teammate = !strcmp(Utils_TF_ColorToTeam(bestinfo->rbottomcolor), TP_PlayerTeam());
if (eyes) if (eyes)
name = tp_name_eyes.string; //duck on 2night2 name = tp_name_eyes.string; //duck on 2night2
@ -2800,7 +2824,9 @@ static void TP_FindPoint (void) {
if (!eyes) if (!eyes)
name = va("%s%s%s", name, name[0] ? " " : "", Skin_To_TFSkin(Info_ValueForKey(bestinfo->userinfo, "skin"))); name = va("%s%s%s", name, name[0] ? " " : "", Skin_To_TFSkin(Info_ValueForKey(bestinfo->userinfo, "skin")));
} else { }
else
{
teammate = !!(cl.teamplay && !strcmp(bestinfo->team, TP_PlayerTeam())); teammate = !!(cl.teamplay && !strcmp(bestinfo->team, TP_PlayerTeam()));
if (eyes) if (eyes)
@ -2819,17 +2845,23 @@ static void TP_FindPoint (void) {
Q_strncpyz (vars.pointloc, TP_LocationName (beststate->origin), sizeof(vars.pointloc)); Q_strncpyz (vars.pointloc, TP_LocationName (beststate->origin), sizeof(vars.pointloc));
vars.pointtype = (teammate && !eyes) ? POINT_TYPE_TEAMMATE : POINT_TYPE_ENEMY; vars.pointtype = (teammate && !eyes) ? POINT_TYPE_TEAMMATE : POINT_TYPE_ENEMY;
} else if (best >= 0) { }
else if (best >= 0)
{
char *p; char *p;
if (!bestitem->cvar) { if (!bestitem->cvar)
{
// armors are special // armors are special
switch (bestent->skinnum) { switch (bestent->skinnum)
{
case 0: p = tp_name_ga.string; break; case 0: p = tp_name_ga.string; break;
case 1: p = tp_name_ya.string; break; case 1: p = tp_name_ya.string; break;
default: p = tp_name_ra.string; default: p = tp_name_ra.string;
} }
} else { }
else
{
p = bestitem->cvar->string; p = bestitem->cvar->string;
} }
@ -2837,7 +2869,8 @@ static void TP_FindPoint (void) {
Q_strncpyz (vars.pointname, p, sizeof(vars.pointname)); Q_strncpyz (vars.pointname, p, sizeof(vars.pointname));
Q_strncpyz (vars.pointloc, TP_LocationName (bestent->origin), sizeof(vars.pointloc)); Q_strncpyz (vars.pointloc, TP_LocationName (bestent->origin), sizeof(vars.pointloc));
} }
else { else
{
nothing: nothing:
Q_strncpyz (vars.pointname, tp_name_nothing.string, sizeof(vars.pointname)); Q_strncpyz (vars.pointname, tp_name_nothing.string, sizeof(vars.pointname));
vars.pointloc[0] = 0; vars.pointloc[0] = 0;