mirror of
https://github.com/nzp-team/quakec.git
synced 2025-02-22 19:51:52 +00:00
CLIENT: Improved scoreboard on HUD
This commit is contained in:
parent
a823256f6e
commit
06d0f9208d
12 changed files with 202 additions and 31 deletions
BIN
.DS_Store
vendored
Normal file
BIN
.DS_Store
vendored
Normal file
Binary file not shown.
|
@ -126,8 +126,6 @@ float screenflash_worktime;
|
||||||
float screenflash_starttime;
|
float screenflash_starttime;
|
||||||
|
|
||||||
.float stance;
|
.float stance;
|
||||||
.float points;
|
|
||||||
.float kills;
|
|
||||||
|
|
||||||
vector camang; // used for punches
|
vector camang; // used for punches
|
||||||
|
|
||||||
|
|
|
@ -1516,16 +1516,56 @@ void() HUD_Broadcast =
|
||||||
Draw_String([x, g_height/2, 0], broadcast_msg, [0.015*g_width, 0.015*g_width, 0], [1, 1, 1], 1, 0);
|
Draw_String([x, g_height/2, 0], broadcast_msg, [0.015*g_width, 0.015*g_width, 0], [1, 1, 1], 1, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void(float y_pos) HUD_DrawMoneyBackDisplay =
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// Center moneyback
|
||||||
|
drawpic([g_width/2 - 48, y_pos], "gfx/hud/moneyback.tga", [96, 24], [1,1,1], 1);
|
||||||
|
// Left
|
||||||
|
for(i = 0; i < 3; i++) {
|
||||||
|
drawpic([(g_width/2 - 48) - (70 * (i + 1)), y_pos], "gfx/hud/moneyback.tga", [96, 24], [1,1,1], 1);
|
||||||
|
}
|
||||||
|
// Right
|
||||||
|
for(i = 0; i < 3; i++) {
|
||||||
|
drawpic([(g_width/2 - 48) + (70 * (i + 1)), y_pos], "gfx/hud/moneyback.tga", [96, 24], [1,1,1], 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void() HUD_Scores =
|
void() HUD_Scores =
|
||||||
{
|
{
|
||||||
int j;
|
|
||||||
vector TEXTCOLOR = [1, 1, 1];
|
vector TEXTCOLOR = [1, 1, 1];
|
||||||
|
|
||||||
|
float header_x_start = -75;
|
||||||
|
float header_x_increment = 65;
|
||||||
|
float scoreboard_text_size = 10;
|
||||||
|
float header_x_pos = header_x_start;
|
||||||
|
|
||||||
if(serverkey("constate") != "disconnected")
|
if(serverkey("constate") != "disconnected")
|
||||||
{
|
{
|
||||||
// Headers
|
Draw_String([5, g_height - scoreboard_text_size - 5], sprintf("Nazi Zombies: Portable %s", build_datetime), [scoreboard_text_size, scoreboard_text_size], TEXTCOLOR, 1, 0);
|
||||||
Draw_String([g_width/2 + 15, 175], "Points", [12, 12], TEXTCOLOR, 1, 0);
|
|
||||||
Draw_String([g_width/2 + 170, 175], "Kills", [12, 12], TEXTCOLOR, 1, 0);
|
// Scoreboard header
|
||||||
|
drawfill([g_width/2 - 271, 177], [270 * 2 + 2, 1], [0.2, 0.2, 0.2], 1, 0);
|
||||||
|
drawfill([g_width/2 - 271, 178 + scoreboard_text_size + 4], [270 * 2 + 2, 1], [0.2, 0.2, 0.2], 1, 0);
|
||||||
|
drawfill([g_width/2 - 271, 178], [1, scoreboard_text_size + 4], [0.2, 0.2, 0.2], 1, 0);
|
||||||
|
drawfill([g_width/2 + 270, 178], [1, scoreboard_text_size + 4], [0.2, 0.2, 0.2], 1, 0);
|
||||||
|
drawfill([g_width/2 - 270, 178], [270 * 2, scoreboard_text_size + 4], [0, 0, 0], 0.80, 0);
|
||||||
|
|
||||||
|
// Name
|
||||||
|
string map_name = serverkey("mapname_pretty");
|
||||||
|
Draw_String([g_width/2 - 265, 180], map_name, [scoreboard_text_size, scoreboard_text_size], TEXTCOLOR, 1, 0);
|
||||||
|
|
||||||
|
Draw_String([g_width/2 + (header_x_pos - getTextWidth("Score", scoreboard_text_size)/2), 180], "Score", [scoreboard_text_size, scoreboard_text_size], TEXTCOLOR, 1, 0);
|
||||||
|
header_x_pos += header_x_increment;
|
||||||
|
Draw_String([g_width/2 + (header_x_pos - getTextWidth("Kills", scoreboard_text_size)/2), 180], "Kills", [scoreboard_text_size, scoreboard_text_size], TEXTCOLOR, 1, 0);
|
||||||
|
header_x_pos += header_x_increment;
|
||||||
|
Draw_String([g_width/2 + (header_x_pos - getTextWidth("Downs", scoreboard_text_size)/2), 180], "Downs", [scoreboard_text_size, scoreboard_text_size], TEXTCOLOR, 1, 0);
|
||||||
|
header_x_pos += header_x_increment;
|
||||||
|
Draw_String([g_width/2 + (header_x_pos - getTextWidth("Revives", scoreboard_text_size)/2), 180], "Revives", [scoreboard_text_size, scoreboard_text_size], TEXTCOLOR, 1, 0);
|
||||||
|
header_x_pos += header_x_increment;
|
||||||
|
Draw_String([g_width/2 + (header_x_pos - getTextWidth("Headshots", scoreboard_text_size)/2), 180], "Headshots", [scoreboard_text_size, scoreboard_text_size], TEXTCOLOR, 1, 0);
|
||||||
|
header_x_pos += header_x_increment;
|
||||||
|
|
||||||
for (int i = 0; i < 4; i = i + 1)
|
for (int i = 0; i < 4; i = i + 1)
|
||||||
{
|
{
|
||||||
|
@ -1542,35 +1582,87 @@ void() HUD_Scores =
|
||||||
default: TEXTCOLOR = [1, 1, 1]; break;
|
default: TEXTCOLOR = [1, 1, 1]; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
float y_pos = (scoreboard_text_size + 5) * i;
|
||||||
// Since positioning is center-aligned, we need to be careful how we do our X and Y
|
|
||||||
// pos. to keep things looking nicely centered and even with different aspect ratios.
|
// Fill
|
||||||
//
|
drawfill([g_width/2 - 270, 195 + y_pos], [270 * 2, scoreboard_text_size + 5], [0, 0, 0], 0.80, 0);
|
||||||
|
drawfill([g_width/2 + (header_x_start - header_x_increment/2), 195 + y_pos], [header_x_increment, scoreboard_text_size + 5], [0.3, 0, 0], 0.15, 0);
|
||||||
|
drawfill([g_width/2 + ((header_x_start + header_x_increment*2) - header_x_increment/2), 195 + y_pos], [header_x_increment, scoreboard_text_size + 5], [0.3, 0, 0], 0.15, 0);
|
||||||
|
drawfill([g_width/2 + ((header_x_start + header_x_increment*4) - header_x_increment/2), 195 + y_pos], [header_x_increment, scoreboard_text_size + 5], [0.3, 0, 0], 0.15, 0);
|
||||||
|
|
||||||
|
// Top
|
||||||
|
if (i == 0)
|
||||||
|
drawfill([g_width/2 - 271, 194 + y_pos], [270 * 2 + 2, 1], [0.2, 0.2, 0.2], 1, 0);
|
||||||
|
|
||||||
|
// Bottom
|
||||||
|
if (player_count == i + 1)
|
||||||
|
drawfill([g_width/2 - 271, 195 + y_pos + scoreboard_text_size + 4], [270 * 2 + 2, 1], [0.2, 0.2, 0.2], 1, 0);
|
||||||
|
|
||||||
// Center moneyback
|
|
||||||
drawpic([g_width/2 - 48, 195 + (30 * i)], "gfx/hud/moneyback.tga", [96, 24], [1,1,1], 1);
|
|
||||||
// Left
|
// Left
|
||||||
for(j = 0; j < 3; j++) {
|
drawfill([g_width/2 - 271, 194 + y_pos], [1, scoreboard_text_size + 6], [0.2, 0.2, 0.2], 1, 0);
|
||||||
drawpic([(g_width/2 - 48) - (70 * (j+1)), 195 + (30 * i)], "gfx/hud/moneyback.tga", [96, 24], [1,1,1], 1);
|
|
||||||
}
|
|
||||||
// Right
|
// Right
|
||||||
for(j = 0; j < 3; j++) {
|
drawfill([g_width/2 + 270, 194 + y_pos], [1, scoreboard_text_size + 6], [0.2, 0.2, 0.2], 1, 0);
|
||||||
drawpic([(g_width/2 - 48) + (70 * (j+1)), 195 + (30 * i)], "gfx/hud/moneyback.tga", [96, 24], [1,1,1], 1);
|
|
||||||
}
|
header_x_pos = header_x_start;
|
||||||
|
|
||||||
// Name
|
// Name
|
||||||
string player_name = getplayerkeyvalue(i, "name");
|
string player_name = getplayerkeyvalue(i, "name");
|
||||||
Draw_String([g_width/2 - 245, 200 + (30 * i)], player_name, [12, 12], TEXTCOLOR, 1, 0);
|
Draw_String([g_width/2 - 265, 197 + y_pos], player_name, [scoreboard_text_size, scoreboard_text_size], TEXTCOLOR, 1, 0);
|
||||||
|
|
||||||
// Points
|
// Score
|
||||||
float point_width = getTextWidth(ftos(client.points), 12);
|
string score_string = ftos(client.points);
|
||||||
float point_x = ((g_width/2) - (point_width)/2) + 52;
|
Draw_String([g_width/2 + (header_x_pos - getTextWidth(score_string, scoreboard_text_size)/2), 197 + y_pos], score_string, [scoreboard_text_size, scoreboard_text_size], TEXTCOLOR, 1, 0);
|
||||||
Draw_String([point_x, 200 + (30 * i)], ftos(client.points), [12, 12], TEXTCOLOR, 1, 0);
|
header_x_pos += header_x_increment;
|
||||||
|
|
||||||
// Kills
|
// Kills
|
||||||
float kill_width = getTextWidth(ftos(client.kills), 12);
|
string kills_string = ftos(client.kills);
|
||||||
float kill_x = ((g_width/2) - (kill_width)/2) + 210;
|
Draw_String([g_width/2 + (header_x_pos - getTextWidth(kills_string, scoreboard_text_size)/2), 197 + y_pos], kills_string, [scoreboard_text_size, scoreboard_text_size], TEXTCOLOR, 1, 0);
|
||||||
Draw_String([kill_x, 200 + (30 * i)], ftos(client.kills), [12, 12], TEXTCOLOR, 1, 0);
|
header_x_pos += header_x_increment;
|
||||||
|
|
||||||
|
// Downs
|
||||||
|
string downs_string = ftos(client.downs);
|
||||||
|
Draw_String([g_width/2 + (header_x_pos - getTextWidth(downs_string, scoreboard_text_size)/2), 197 + y_pos], downs_string, [scoreboard_text_size, scoreboard_text_size], TEXTCOLOR, 1, 0);
|
||||||
|
header_x_pos += header_x_increment;
|
||||||
|
|
||||||
|
// Revives
|
||||||
|
string revives_string = ftos(client.revives);
|
||||||
|
Draw_String([g_width/2 + (header_x_pos - getTextWidth(revives_string, scoreboard_text_size)/2), 197 + y_pos], revives_string, [scoreboard_text_size, scoreboard_text_size], TEXTCOLOR, 1, 0);
|
||||||
|
header_x_pos += header_x_increment;
|
||||||
|
|
||||||
|
// Headshots
|
||||||
|
string headshots_string = ftos(client.headshots);
|
||||||
|
Draw_String([g_width/2 + (header_x_pos - getTextWidth(headshots_string, scoreboard_text_size)/2), 197 + y_pos], headshots_string, [scoreboard_text_size, scoreboard_text_size], TEXTCOLOR, 1, 0);
|
||||||
|
|
||||||
|
// Ping
|
||||||
|
float ping_num_bars;
|
||||||
|
vector ping_bar_color = [0, 1, 0];
|
||||||
|
|
||||||
|
if (client.ping < 100) {
|
||||||
|
ping_num_bars = 4;
|
||||||
|
} else if (client.ping < 200) {
|
||||||
|
ping_num_bars = 3;
|
||||||
|
} else if (client.ping < 300) {
|
||||||
|
ping_num_bars = 2;
|
||||||
|
ping_bar_color = [1, 0.5, 0];
|
||||||
|
} else {
|
||||||
|
ping_num_bars = 1;
|
||||||
|
ping_bar_color = [1, 0, 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
header_x_pos += 5 + header_x_increment/2;
|
||||||
|
float ping_bar_width = 2;
|
||||||
|
float ping_bar_height = 4;
|
||||||
|
float ping_bar_height_increment = 2;
|
||||||
|
|
||||||
|
string ping_string = sprintf("%dms", client.ping);
|
||||||
|
Draw_String([g_width/2 + ((header_x_pos + 28) - getTextWidth(ping_string, scoreboard_text_size - 2)/2), 199 + y_pos], ping_string, [scoreboard_text_size - 2, scoreboard_text_size - 2], TEXTCOLOR, 1, 0);
|
||||||
|
|
||||||
|
for(float bars = ping_num_bars; bars > 0; bars--) {
|
||||||
|
drawfill([g_width/2 + header_x_pos, 197 + y_pos + (11 - ping_bar_height)], [ping_bar_width, ping_bar_height], ping_bar_color, 1, 0);
|
||||||
|
ping_bar_height += ping_bar_height_increment;
|
||||||
|
header_x_pos += 3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -419,8 +419,12 @@ noref void(float isnew) CSQC_Ent_Update =
|
||||||
self.stance = readbyte();
|
self.stance = readbyte();
|
||||||
self.points = readfloat(); // FIXME: this should be made a short, but I know we use price of 1 for some test maps, so I can't do /10 *10 shenanigans.
|
self.points = readfloat(); // FIXME: this should be made a short, but I know we use price of 1 for some test maps, so I can't do /10 *10 shenanigans.
|
||||||
self.kills = readshort();
|
self.kills = readshort();
|
||||||
|
self.headshots = readshort();
|
||||||
|
self.downs = readshort();
|
||||||
|
self.revives = readshort();
|
||||||
self.is_in_menu = readbyte();
|
self.is_in_menu = readbyte();
|
||||||
self.is_spectator = readbyte();
|
self.is_spectator = readbyte();
|
||||||
|
self.ping = readshort();
|
||||||
|
|
||||||
// set for HUD_PlayerDebugInfo
|
// set for HUD_PlayerDebugInfo
|
||||||
player_velocity = self.velocity;
|
player_velocity = self.velocity;
|
||||||
|
|
|
@ -542,6 +542,8 @@ Player_SendEntity
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
float Player_SendEntity( entity ePVEnt, float flChanged ) {
|
float Player_SendEntity( entity ePVEnt, float flChanged ) {
|
||||||
|
self.ping = infokeyf(self, "ping");
|
||||||
|
|
||||||
WriteByte( MSG_ENTITY, 1 );
|
WriteByte( MSG_ENTITY, 1 );
|
||||||
WriteCoord( MSG_ENTITY, self.origin_x ); // Position X
|
WriteCoord( MSG_ENTITY, self.origin_x ); // Position X
|
||||||
WriteCoord( MSG_ENTITY, self.origin_y ); // Position Y
|
WriteCoord( MSG_ENTITY, self.origin_y ); // Position Y
|
||||||
|
@ -560,8 +562,12 @@ float Player_SendEntity( entity ePVEnt, float flChanged ) {
|
||||||
WriteByte( MSG_ENTITY, self.stance ); // Player Stance
|
WriteByte( MSG_ENTITY, self.stance ); // Player Stance
|
||||||
WriteFloat( MSG_ENTITY, self.points ); // Player Score
|
WriteFloat( MSG_ENTITY, self.points ); // Player Score
|
||||||
WriteShort( MSG_ENTITY, self.kills ); // Player Kills
|
WriteShort( MSG_ENTITY, self.kills ); // Player Kills
|
||||||
|
WriteShort( MSG_ENTITY, self.headshots ); // Player Headshots
|
||||||
|
WriteShort( MSG_ENTITY, self.downs ); // Player Downs
|
||||||
|
WriteShort( MSG_ENTITY, self.revives ); // Player Revives
|
||||||
WriteByte( MSG_ENTITY, self.is_in_menu ); // Player is in a Menu State
|
WriteByte( MSG_ENTITY, self.is_in_menu ); // Player is in a Menu State
|
||||||
WriteByte( MSG_ENTITY, self.is_spectator ); // Player is spectating
|
WriteByte( MSG_ENTITY, self.is_spectator ); // Player is spectating
|
||||||
|
WriteShort( MSG_ENTITY, self.ping ); // Player's latency to the server in ms
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,14 +100,11 @@ entity local_client;
|
||||||
.vector new_ofs;
|
.vector new_ofs;
|
||||||
|
|
||||||
//money
|
//money
|
||||||
.float points;
|
|
||||||
.float cost;
|
.float cost;
|
||||||
.float cost2;
|
.float cost2;
|
||||||
|
|
||||||
//stats
|
//stats
|
||||||
.float score;
|
.float score;
|
||||||
.float kills;
|
|
||||||
.float headshots;
|
|
||||||
|
|
||||||
#ifdef FTE
|
#ifdef FTE
|
||||||
|
|
||||||
|
|
|
@ -409,6 +409,27 @@ void() worldspawn =
|
||||||
|
|
||||||
// Update the cvar for the server.
|
// Update the cvar for the server.
|
||||||
cvar_set("sv_gravity", ftos(sv_gravity * world.gravity));
|
cvar_set("sv_gravity", ftos(sv_gravity * world.gravity));
|
||||||
|
|
||||||
|
#ifdef FTE
|
||||||
|
|
||||||
|
// We need to get the currently loaded map's pretty name
|
||||||
|
// (if it exists) so we can send it to clients or broadcast
|
||||||
|
// it.
|
||||||
|
string mapname_pretty;
|
||||||
|
float map_txt_file = fopen(sprintf("maps/%s.txt", mapname), FILE_READ);
|
||||||
|
|
||||||
|
if (map_txt_file == -1) {
|
||||||
|
mapname_pretty = mapname;
|
||||||
|
} else {
|
||||||
|
mapname_pretty = strtrim((fgets(map_txt_file)));
|
||||||
|
fclose(map_txt_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
cvar_set("mapname_pretty", mapname_pretty);
|
||||||
|
localcmd(sprintf("serverinfo mapname_pretty %s\n", mapname_pretty));
|
||||||
|
|
||||||
|
#endif // FTE
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void() SpectatorConnect =
|
void() SpectatorConnect =
|
||||||
|
|
|
@ -44,6 +44,9 @@ void() LastStand_SoloRevive =
|
||||||
// Give the player their score back.
|
// Give the player their score back.
|
||||||
Player_AddScore(self.owner, self.owner.requirespower, false);
|
Player_AddScore(self.owner, self.owner.requirespower, false);
|
||||||
|
|
||||||
|
// Technically, this counts as a revive, I suppose.
|
||||||
|
self.owner.revives++;
|
||||||
|
|
||||||
// No need for us to exist anymore, goodbye!
|
// No need for us to exist anymore, goodbye!
|
||||||
remove(self);
|
remove(self);
|
||||||
};
|
};
|
||||||
|
@ -93,6 +96,9 @@ void(entity client) LastStand_Penalize =
|
||||||
self = old_self;
|
self = old_self;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Increment stat
|
||||||
|
client.downs++;
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -381,8 +387,10 @@ void() LastStand_TouchReviveTrigger =
|
||||||
|
|
||||||
// Reviving has been executed for the full duration..
|
// Reviving has been executed for the full duration..
|
||||||
if (self.ltime < time) {
|
if (self.ltime < time) {
|
||||||
// Reward the revivee with the points the downed client lost
|
// Reward the revivee with the points the downed client lost,
|
||||||
|
// and increment their revives stat.
|
||||||
Player_AddScore(other, self.owner.requirespower, false);
|
Player_AddScore(other, self.owner.requirespower, false);
|
||||||
|
self.owner.revives++;
|
||||||
|
|
||||||
entity old_self = self;
|
entity old_self = self;
|
||||||
self = self.owner;
|
self = self.owner;
|
||||||
|
|
|
@ -310,8 +310,16 @@ float map_compatibility_mode;
|
||||||
#define STAT_WEAPONSKIN 68
|
#define STAT_WEAPONSKIN 68
|
||||||
#define STAT_PERKS 69
|
#define STAT_PERKS 69
|
||||||
|
|
||||||
|
// Misc. player statistics
|
||||||
.float playernum;
|
.float playernum;
|
||||||
.float is_spectator;
|
.float is_spectator;
|
||||||
|
.float ping;
|
||||||
|
.float kills;
|
||||||
|
.float headshots;
|
||||||
|
.float downs;
|
||||||
|
.float revives;
|
||||||
|
.float points;
|
||||||
|
|
||||||
float game_over;
|
float game_over;
|
||||||
|
|
||||||
#ifdef FTE
|
#ifdef FTE
|
||||||
|
|
6
tools/compile-and-run.sh
Executable file
6
tools/compile-and-run.sh
Executable file
|
@ -0,0 +1,6 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
./qc-compiler-gnu.sh
|
||||||
|
cp ../build/fte/* ~/nzp-mac/nzp/
|
||||||
|
cd ~/nzp-mac/
|
||||||
|
wine nzportable-sdl64.exe +map ndu
|
0
tools/conhistory.txt
Normal file
0
tools/conhistory.txt
Normal file
31
tools/test-dedicated.sh
Executable file
31
tools/test-dedicated.sh
Executable file
|
@ -0,0 +1,31 @@
|
||||||
|
# Compile and copy files
|
||||||
|
./qc-compiler-gnu.sh
|
||||||
|
cp ../build/fte/* ~/nzp-mac/nzp/
|
||||||
|
cp ../build/fte/* ~/nzp-dedi/nzp/
|
||||||
|
|
||||||
|
# Start the dedicated server
|
||||||
|
cd ~/nzp-dedi/
|
||||||
|
nohup wine nzportable64.exe -dedicated +map ndu +hostname dedi-test > dedi.log 2>&1 &
|
||||||
|
disown
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
# Start the first client
|
||||||
|
cd ~/nzp-mac/
|
||||||
|
nohup wine nzportable-sdl64.exe +vid_width 640 +vid_height 480 +name client_1 +connect localhost > client_0.log 2>&1 &
|
||||||
|
disown
|
||||||
|
sleep 3
|
||||||
|
|
||||||
|
# Start the second client
|
||||||
|
nohup wine nzportable-sdl64.exe +vid_width 640 +vid_height 480 +name client_2 +connect localhost > client_1.log 2>&1 &
|
||||||
|
disown
|
||||||
|
sleep 3
|
||||||
|
|
||||||
|
Start the third client
|
||||||
|
nohup wine nzportable-sdl64.exe +vid_width 640 +vid_height 480 +name client_3 +connect localhost > client_1.log 2>&1 &
|
||||||
|
disown
|
||||||
|
sleep 3
|
||||||
|
|
||||||
|
Start the fourth client
|
||||||
|
nohup wine nzportable-sdl64.exe +vid_width 640 +vid_height 480 +name client_4 +connect localhost > client_1.log 2>&1 &
|
||||||
|
disown
|
||||||
|
sleep 3
|
Loading…
Reference in a new issue