[nexuiz-commits] r8499 - in trunk/data: . qcsrc/client qcsrc/common qcsrc/server

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Fri Jan 15 16:53:43 EST 2010


Author: fruitiex
Date: 2010-01-15 16:53:43 -0500 (Fri, 15 Jan 2010)
New Revision: 8499

Modified:
   trunk/data/defaultNexuiz.cfg
   trunk/data/qcsrc/client/Main.qc
   trunk/data/qcsrc/client/main.qh
   trunk/data/qcsrc/client/sbar.qc
   trunk/data/qcsrc/common/constants.qh
   trunk/data/qcsrc/common/gamecommand.qc
   trunk/data/qcsrc/common/util.qh
   trunk/data/qcsrc/server/cl_client.qc
   trunk/data/qcsrc/server/clientcommands.qc
   trunk/data/qcsrc/server/g_world.qc
   trunk/data/qcsrc/server/gamecommand.qc
   trunk/data/qcsrc/server/miscfunctions.qc
   trunk/data/qcsrc/server/race.qc
Log:
race/cts rankings (default 15 best)


Modified: trunk/data/defaultNexuiz.cfg
===================================================================
--- trunk/data/defaultNexuiz.cfg	2010-01-13 20:37:01 UTC (rev 8498)
+++ trunk/data/defaultNexuiz.cfg	2010-01-15 21:53:43 UTC (rev 8499)
@@ -1538,6 +1538,7 @@
 set g_showweaponspawns 0	"1: display sprites for weapon spawns found on the map when a weapon key is pressed and the weapon is not available"
 
 alias records "cmd records"
+alias rankings "cmd rankings"
 
 // ballistics use physical units, but qu based
 //   Quake-Newton: 1 qN  = 1 qu * 1 g / 1 s^2

Modified: trunk/data/qcsrc/client/Main.qc
===================================================================
--- trunk/data/qcsrc/client/Main.qc	2010-01-13 20:37:01 UTC (rev 8498)
+++ trunk/data/qcsrc/client/Main.qc	2010-01-15 21:53:43 UTC (rev 8499)
@@ -1048,12 +1048,60 @@
 			break;
 		case RACE_NET_SPEED_AWARD:
 			race_speedaward = ReadShort();
+			if(race_speedaward_holder)
+				strunzone(race_speedaward_holder);
 			race_speedaward_holder = strzone(ReadString());
 			break;
 		case RACE_NET_SPEED_AWARD_BEST:
 			race_speedaward_alltimebest = ReadShort();
+			if(race_speedaward_alltimebest_holder)
+				strunzone(race_speedaward_alltimebest_holder);
 			race_speedaward_alltimebest_holder = strzone(ReadString());
 			break;
+		case RACE_NET_SERVER_RANKINGS:
+			float pos, prevpos, del;
+			pos = ReadShort();
+			prevpos = ReadShort();
+			del = ReadShort();
+
+			// move other rankings out of the way
+			float i;
+			if (prevpos) {
+				for (i=prevpos-1;i>pos-1;--i) {
+					grecordtime[i] = grecordtime[i-1];
+					if(grecordholder[i])
+						strunzone(grecordholder[i]);
+					grecordholder[i] = strzone(grecordholder[i-1]);
+				}
+			} else if (del) { // a record has been deleted by the admin
+				for (i=pos-1; i<= RANKINGS_CNT-1; ++i) {
+					if (i == RANKINGS_CNT-1) { // clear out last record
+						grecordtime[i] = 0;
+						if (grecordholder[i])
+							strunzone(grecordholder[i]);
+						grecordholder[i] = string_null;
+					}
+					else {
+						grecordtime[i] = grecordtime[i+1];
+						if (grecordholder[i])
+							strunzone(grecordholder[i]);
+						grecordholder[i] = strzone(grecordholder[i+1]);
+					}
+				}
+			} else { // player has no ranked record yet
+				for (i=RANKINGS_CNT-1;i>pos-1;--i) {
+					grecordtime[i] = grecordtime[i-1];
+					if(grecordholder[i])
+						strunzone(grecordholder[i]);
+					grecordholder[i] = strzone(grecordholder[i-1]);
+				}
+			}
+
+			// store new ranking
+			if(grecordholder[pos-1] != "")
+				strunzone(grecordholder[pos-1]);
+			grecordholder[pos-1] = strzone(ReadString());
+			grecordtime[pos-1] = ReadInt24_t();
 	}
 }
 

Modified: trunk/data/qcsrc/client/main.qh
===================================================================
--- trunk/data/qcsrc/client/main.qh	2010-01-13 20:37:01 UTC (rev 8498)
+++ trunk/data/qcsrc/client/main.qh	2010-01-15 21:53:43 UTC (rev 8499)
@@ -98,6 +98,9 @@
 vector sbar_fontsize;
 vector sbar_fontsize_spec;
 
+float RANKINGS_RECEIVED_CNT;
+string grecordholder[RANKINGS_CNT];
+float grecordtime[RANKINGS_CNT];
 //float csqc_flags;
 
 entity playerslots[255]; // 255 is engine limit on maxclients

Modified: trunk/data/qcsrc/client/sbar.qc
===================================================================
--- trunk/data/qcsrc/client/sbar.qc	2010-01-13 20:37:01 UTC (rev 8498)
+++ trunk/data/qcsrc/client/sbar.qc	2010-01-15 21:53:43 UTC (rev 8499)
@@ -1239,6 +1239,68 @@
 	return pos;
 }
 
+string race_PlaceName(float pos) {
+	if(pos == 1)
+		return "1st";
+	else if(pos == 2)
+		return "2nd";
+	else if(pos == 3)
+		return "3rd";
+	else
+		return strcat(ftos(pos), "th");
+}
+
+vector Sbar_DrawScoreboardRankings(vector pos, entity pl,  vector rgb, vector bg_size)
+{
+	float i;
+	RANKINGS_RECEIVED_CNT = 0;
+		for (i=RANKINGS_CNT-1; i>=0; --i)
+			if (grecordtime[i])
+				RANKINGS_RECEIVED_CNT = RANKINGS_RECEIVED_CNT + 1;
+
+	if (RANKINGS_RECEIVED_CNT == 0)
+		return pos;
+
+	float is_spec;
+	is_spec = (GetPlayerColor(pl.sv_entnum) == COLOR_SPECTATOR);
+	vector hl_rgb;
+		hl_rgb_x = cvar("sbar_color_bg_r") + 0.5;
+		hl_rgb_y = cvar("sbar_color_bg_g") + 0.5;
+		hl_rgb_z = cvar("sbar_color_bg_b") + 0.5;
+
+	pos_y += sbar_fontsize_y;
+	drawstring(pos, strcat("Rankings"), sbar_fontsize, '1 1 1', sbar_scoreboard_alpha_fg, DRAWFLAG_NORMAL);
+	pos_y += sbar_fontsize_y;
+	vector tmp;
+	tmp_x = sbwidth;
+	tmp_y = sbar_fontsize_y * RANKINGS_RECEIVED_CNT;
+
+	drawpic_tiled(pos, "gfx/hud/sb_scoreboard_bg", bg_size, tmp, rgb * sbar_color_bg_team, sbar_scoreboard_alpha_bg, DRAWFLAG_NORMAL);
+	drawborderlines(sbar_border_thickness, pos, tmp, '0 0 0', sbar_scoreboard_alpha_bg * 0.75, DRAWFLAG_NORMAL);
+
+	// row highlighting
+	for(i = 0; i<RANKINGS_RECEIVED_CNT; ++i)
+	{
+		string n, p;
+		float t;
+		t = grecordtime[i];
+		if (t == 0)
+			continue;
+		n = grecordholder[i];
+		p = race_PlaceName(i+1);
+		if(grecordholder[i] == GetPlayerName(player_localentnum - 1))
+			drawfill(pos, '1 0 0' * sbwidth + '0 1 0' * sbar_fontsize_y, hl_rgb, sbar_scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);	
+		else if(!mod(i, 2) && sbar_scoreboard_highlight)
+			drawfill(pos, '1 0 0' * sbwidth + '0 1 0' * sbar_fontsize_y, hl_rgb, sbar_scoreboard_highlight_alpha, DRAWFLAG_NORMAL);	
+		drawstring(pos, p, sbar_fontsize, '1 1 1', sbar_scoreboard_alpha_fg, DRAWFLAG_NORMAL);
+		drawstring(pos + '3 0 0' * sbar_fontsize_x, TIME_ENCODED_TOSTRING(t), sbar_fontsize, '1 1 1', sbar_scoreboard_alpha_fg, DRAWFLAG_NORMAL);
+		drawcolorcodedstring(pos + '8 0 0' * sbar_fontsize_x, n, sbar_fontsize, sbar_scoreboard_alpha_fg, DRAWFLAG_NORMAL);
+		pos += '0 1 0' * sbar_fontsize_y;
+	}
+
+	return pos;
+}
+
 float scoreboard_bottom;
 float sbar_scoreboard_fade_alpha;
 float sbar_woulddrawscoreboard_prev;
@@ -1346,6 +1408,7 @@
 			drawcolorcodedstring(pos, strcat("All-time fastest: ", ftos(race_speedaward_alltimebest), " (", race_speedaward_alltimebest_holder, ")"), sbar_fontsize, sbar_scoreboard_alpha_fg, DRAWFLAG_NORMAL);
 			pos_y += 1.25 * sbar_fontsize_y;
 		}
+		pos = Sbar_DrawScoreboardRankings(pos, pl, rgb, bg_size);
 	}
 	else if(cvar("sbar_accuracy") && spectatee_status != -1) {
 		if(teamplay)

Modified: trunk/data/qcsrc/common/constants.qh
===================================================================
--- trunk/data/qcsrc/common/constants.qh	2010-01-13 20:37:01 UTC (rev 8498)
+++ trunk/data/qcsrc/common/constants.qh	2010-01-15 21:53:43 UTC (rev 8499)
@@ -65,6 +65,8 @@
 const float RACE_NET_SERVER_RECORD = 8; // server record, sent to client
 const float RACE_NET_SPEED_AWARD = 9; // speed award, sent to client
 const float RACE_NET_SPEED_AWARD_BEST = 10; // all time best speed award, sent to client
+const float RACE_NET_SERVER_RANKINGS = 11;
+const float RANKINGS_CNT = 15;
 
 const float ENT_CLIENT = 0;
 const float ENT_CLIENT_DEAD = 1;

Modified: trunk/data/qcsrc/common/gamecommand.qc
===================================================================
--- trunk/data/qcsrc/common/gamecommand.qc	2010-01-13 20:37:01 UTC (rev 8498)
+++ trunk/data/qcsrc/common/gamecommand.qc	2010-01-15 21:53:43 UTC (rev 8499)
@@ -199,6 +199,7 @@
 		print("  maplist lsmaps\n");
 		print("  addtolist variable addedvalue\n");
 		print("  records\n");
+		print("  rankings (map argument optional)\n");
 		return TRUE;
 	}
 	
@@ -810,6 +811,10 @@
 	else if(argv(0) == "records") {
 		print(records_reply);
 		return TRUE;
+	}
+	else if(argv(0) == "rankings") {
+		print(rankings_reply);
+		return TRUE;
 #ifdef MENUQC
 	} else if(argv(0) == "cp") {
 		if(argc >= 2)

Modified: trunk/data/qcsrc/common/util.qh
===================================================================
--- trunk/data/qcsrc/common/util.qh	2010-01-13 20:37:01 UTC (rev 8498)
+++ trunk/data/qcsrc/common/util.qh	2010-01-15 21:53:43 UTC (rev 8499)
@@ -161,7 +161,7 @@
 float compressShotOrigin(vector v);
 vector decompressShotOrigin(float f);
 
-string records_reply, lsmaps_reply, maplist_reply; // cached replies
+string records_reply, rankings_reply, lsmaps_reply, maplist_reply; // cached replies
 
 float RandomSelection_totalweight;
 float RandomSelection_best_priority;

Modified: trunk/data/qcsrc/server/cl_client.qc
===================================================================
--- trunk/data/qcsrc/server/cl_client.qc	2010-01-13 20:37:01 UTC (rev 8498)
+++ trunk/data/qcsrc/server/cl_client.qc	2010-01-15 21:53:43 UTC (rev 8499)
@@ -1,4 +1,5 @@
-void race_send_recordtime(float t, float msg);
+void race_send_recordtime(float msg);
+void race_SendRankings(float pos, float prevpos, float del, float msg);
 
 void send_CSQC_teamnagger() {
 	WriteByte(0, SVC_TEMPENTITY);
@@ -1492,12 +1493,17 @@
 			rr = RACE_RECORD;
 		t = stof(db_get(ServerProgsDB, strcat(GetMapname(), rr, "time")));
 
-		race_send_recordtime(t, MSG_ONE);
+		race_send_recordtime(MSG_ONE);
 		race_send_speedaward(MSG_ONE);
 
 		speedaward_alltimebest = stof(db_get(ServerProgsDB, strcat(GetMapname(), rr, "speed/speed")));
 		speedaward_alltimebest_holder = db_get(ServerProgsDB, strcat(GetMapname(), rr, "speed/netname"));
 		race_send_speedaward_alltimebest(MSG_ONE);
+
+		float i;
+		for (i = 1; i <= RANKINGS_CNT; ++i) {
+			race_SendRankings(i, 0, 0, MSG_ONE);
+		}
 	}
 	else if(cvar("sv_teamnagger") && !g_ca) // teamnagger is currently bad for ca
 		send_CSQC_teamnagger();

Modified: trunk/data/qcsrc/server/clientcommands.qc
===================================================================
--- trunk/data/qcsrc/server/clientcommands.qc	2010-01-13 20:37:01 UTC (rev 8498)
+++ trunk/data/qcsrc/server/clientcommands.qc	2010-01-15 21:53:43 UTC (rev 8499)
@@ -340,6 +340,8 @@
 		sprint(self, lsmaps_reply);
 	} else if(cmd == "records") {
 		sprint(self, records_reply);
+	} else if(cmd == "rankings") {
+		sprint(self, rankings_reply);
 	} else if(cmd == "voice") {
 		if(tokens >= 3)
 			VoiceMessage(argv(1), substring(s, argv_start_index(2), argv_end_index(-1) - argv_start_index(2)));

Modified: trunk/data/qcsrc/server/g_world.qc
===================================================================
--- trunk/data/qcsrc/server/g_world.qc	2010-01-13 20:37:01 UTC (rev 8498)
+++ trunk/data/qcsrc/server/g_world.qc	2010-01-15 21:53:43 UTC (rev 8499)
@@ -674,6 +674,7 @@
 	MapInfo_ClearTemps();
 
 	records_reply = strzone(getrecords());
+	rankings_reply = strzone(getrankings());
 
 	ClientInit_Spawn();
 	RandomSeed_Spawn();

Modified: trunk/data/qcsrc/server/gamecommand.qc
===================================================================
--- trunk/data/qcsrc/server/gamecommand.qc	2010-01-13 20:37:01 UTC (rev 8498)
+++ trunk/data/qcsrc/server/gamecommand.qc	2010-01-15 21:53:43 UTC (rev 8499)
@@ -1,4 +1,5 @@
 string GotoMap(string m);
+void race_DeleteTime(float pos);
 
 float FullTraceFraction(vector a, vector mi, vector ma, vector b)
 {
@@ -930,6 +931,13 @@
 		print(records_reply);
 		return;
 	}
+	if (argv(0) == "rankings")
+	{
+		strunzone(rankings_reply);
+		rankings_reply = strzone(getrankings());
+		print(rankings_reply);
+		return;
+	}
 
 	if(argv(0) == "cointoss")
 	{
@@ -1326,6 +1334,11 @@
 
 		return;
 	}
+	if(argv(0) == "delrec")
+	{
+		race_DeleteTime(stof(argv(1)));
+		return;
+	}
 
 	print("Invalid command. For a list of supported commands, try sv_cmd help.\n");
 }

Modified: trunk/data/qcsrc/server/miscfunctions.qc
===================================================================
--- trunk/data/qcsrc/server/miscfunctions.qc	2010-01-13 20:37:01 UTC (rev 8498)
+++ trunk/data/qcsrc/server/miscfunctions.qc	2010-01-15 21:53:43 UTC (rev 8499)
@@ -5,6 +5,10 @@
 
 void() spawnfunc_info_player_deathmatch; // needed for the other spawnpoints
 void() spawnpoint_use;
+float race_GetTime(float pos);
+string race_GetName(float pos);
+string race_PlaceName(float pos);
+string GetMapname();
 string ColoredTeamName(float t);
 
 string admin_name(void)
@@ -2230,6 +2234,37 @@
         return strcat("Records on this server:\n", s);
 }
 
+string getrankings()
+{
+    string n;
+    float t;
+    float i;
+    string s;
+    string p;
+    string map;
+
+    s = "";
+
+    map = GetMapname();
+
+    for (i = 1; i <= RANKINGS_CNT; ++i)
+    {
+        t = race_GetTime(i);
+	if (t == 0)
+	    continue;
+	n = race_GetName(i);
+	p = race_PlaceName(i);
+        s = strcat(s, strpad(8, p), " ", strpad(-8, TIME_ENCODED_TOSTRING(t)), " ", n, "\n");
+    }
+
+    MapInfo_ClearTemps();
+
+    if (s == "")
+        return strcat("No records are available for the map: ", map, "\n");
+    else
+        return strcat("Records for ", map, ":\n", s);
+}
+
 float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance)
 {
     float m, i;

Modified: trunk/data/qcsrc/server/race.qc
===================================================================
--- trunk/data/qcsrc/server/race.qc	2010-01-13 20:37:01 UTC (rev 8498)
+++ trunk/data/qcsrc/server/race.qc	2010-01-15 21:53:43 UTC (rev 8499)
@@ -96,15 +96,222 @@
 			race_SendNextCheckpoint(msg_entity.enemy, 1);
 }
 
-void race_send_recordtime(float t, float msg)
+string rr;
+float grecordtime[RANKINGS_CNT];
+string grecordholder[RANKINGS_CNT];
+float worst_time; // last ranked time
+float have_recs; // have we already read the records from the database before?
+float race_GetTime(float pos) {
+	if(g_cts)
+		rr = CTS_RECORD;
+	else
+		rr = RACE_RECORD;
+
+	if (!have_recs) { // I guess this is better than checking if the first array item is empty, rumor has it that arrays are slow
+		float i;
+		for(i=0;i<RANKINGS_CNT;++i) {
+			grecordtime[i] = stof(db_get(ServerProgsDB, strcat(GetMapname(), rr, "time", ftos(i))));
+			grecordholder[i] = strzone(db_get(ServerProgsDB, strcat(GetMapname(), rr, "netname", ftos(i))));
+		}
+		grecordtime[0] = stof(db_get(ServerProgsDB, strcat(GetMapname(), rr, "time")));
+		grecordholder[0] = strzone(db_get(ServerProgsDB, strcat(GetMapname(), rr, "netname")));
+		worst_time = stof(db_get(ServerProgsDB, strcat(GetMapname(), rr, strcat("time", ftos(RANKINGS_CNT-1)))));
+		have_recs = 1;
+	}
+
+	return grecordtime[pos-1];
+}
+
+string race_GetName(float pos) { // these other functions assume that race_GetTime has been called >= once before
+	return grecordholder[pos-1];
+}
+
+float race_CheckName(string netname) { // Does the name already exist in rankings? In that case, where? (otherwise 0)
+	float i;
+	for (i=RANKINGS_CNT-1;i>=0;--i)
+		if(grecordholder[i] == netname)
+			return i+1;
+	return 0;
+}
+
+float race_GetPos(float t) {
+	float i;
+
+	if(worst_time == 0)
+	for (i=0;i<RANKINGS_CNT;++i)
+		if (grecordtime[i] == 0 || grecordtime[i] > t)
+			return i+1;
+
+	for (i=RANKINGS_CNT-1;i>=0;--i)
+		if (grecordtime[i] > t)
+			return i+1;
+	return 0;
+}
+
+void race_send_recordtime(float msg)
 {
 	// send the server best time
 	WriteByte(msg, SVC_TEMPENTITY);
 	WriteByte(msg, TE_CSQC_RACE);
 	WriteByte(msg, RACE_NET_SERVER_RECORD);
-	WriteInt24_t(msg, t);
+	WriteInt24_t(msg, race_GetTime(1));
 }
 
+void race_SendRankings(float pos, float prevpos, float del, float msg)
+{
+	WriteByte(msg, SVC_TEMPENTITY);
+	WriteByte(msg, TE_CSQC_RACE);
+	WriteByte(msg, RACE_NET_SERVER_RANKINGS);
+	WriteShort(msg, pos);
+	WriteShort(msg, prevpos);
+	WriteShort(msg, del);
+	WriteString(msg, race_GetName(pos));
+	WriteInt24_t(msg, race_GetTime(pos));
+}
+
+string race_PlaceName(float pos) {
+	if(pos == 1)
+		return "1st";
+	else if(pos == 2)
+		return "2nd";
+	else if(pos == 3)
+		return "3rd";
+	else
+		return strcat(ftos(pos), "th");
+}
+
+void race_SetTime(entity e, float t) {
+	if (worst_time && t > worst_time)
+		return;
+
+	float oldrec;
+	string oldname;
+	float pos;
+	pos = race_GetPos(t);
+
+	float prevpos = race_CheckName(e.netname);
+	if (prevpos && (prevpos < pos || !pos))
+	{
+		oldrec = race_GetTime(prevpos);
+		string recorddifference = strcat(" ^1[+", TIME_ENCODED_TOSTRING(t - oldrec), "]");
+		bprint(e.netname, "^1 couldn't break their ", race_PlaceName(prevpos), " place record of ", TIME_ENCODED_TOSTRING(oldrec), recorddifference, "\n");
+
+		return;
+	} else if (!pos) { // no ranking, time worse than the worst ranked
+		string recorddifference = strcat(" ^1[+", TIME_ENCODED_TOSTRING(t - grecordtime[RANKINGS_CNT-1]), "]");
+		bprint(e.netname, "^1 couldn't break the ", race_PlaceName(RANKINGS_CNT), " place record of ", TIME_ENCODED_TOSTRING(grecordtime[RANKINGS_CNT-1]), recorddifference, "\n");
+		return;
+	}
+
+
+	// move other rankings out of the way
+	float i;
+	if (prevpos) { // player improved his existing record
+		if(prevpos == pos) {
+			oldrec = grecordtime[pos-1];
+		}
+		for (i=prevpos-1;i>pos-1;--i) {
+			db_put(ServerProgsDB, strcat(GetMapname(), rr, "time", ftos(i)), ftos(grecordtime[i-1]));
+			db_put(ServerProgsDB, strcat(GetMapname(), rr, "netname", ftos(i)), grecordholder[i-1]);
+			if(i == prevpos-1) {
+				oldrec = grecordtime[i];
+				oldname = grecordholder[i];
+			}
+			grecordtime[i] = grecordtime[i-1];
+			if (grecordholder[i])
+				strunzone(grecordholder[i]);
+			grecordholder[i] = strzone(grecordholder[i-1]);
+		}
+	} else { // player has no ranked record yet
+		for (i=RANKINGS_CNT-1;i>pos-1;--i) {
+			db_put(ServerProgsDB, strcat(GetMapname(), rr, "time", ftos(i)), ftos(grecordtime[i-1]));
+			db_put(ServerProgsDB, strcat(GetMapname(), rr, "netname", ftos(i)), grecordholder[i-1]);
+			grecordtime[i] = grecordtime[i-1];
+			if (grecordholder[i])
+				strunzone(grecordholder[i]);
+			grecordholder[i] = strzone(grecordholder[i-1]);
+		}
+	}
+	
+	// store new ranking
+	if (pos == 1) {
+		db_put(ServerProgsDB, strcat(GetMapname(), rr, "time"), ftos(t));
+		db_put(ServerProgsDB, strcat(GetMapname(), rr, "netname"), e.netname);
+		grecordtime[0] = t;
+		if (grecordholder[0])
+			strunzone(grecordholder[0]);
+		grecordholder[0] = strzone(e.netname);
+		write_recordmarker(e, time - TIME_DECODE(t), TIME_DECODE(t));
+		race_send_recordtime(MSG_ALL);
+	} else {
+		db_put(ServerProgsDB, strcat(GetMapname(), rr, "time", ftos(pos-1)), ftos(t));
+		db_put(ServerProgsDB, strcat(GetMapname(), rr, "netname", ftos(pos-1)), e.netname);
+		grecordtime[pos-1] = t;
+		if (grecordholder[pos-1])
+			strunzone(grecordholder[pos-1]);
+		grecordholder[pos-1] = strzone(e.netname);
+	}
+
+	if (pos == RANKINGS_CNT)
+		worst_time = t;
+
+	race_SendRankings(pos, prevpos, 0, MSG_ALL);
+	if(rankings_reply)
+		strunzone(rankings_reply);
+	rankings_reply = strzone(getrankings());
+	if(pos == prevpos) {
+		string recorddifference = strcat(" ^3[-", TIME_ENCODED_TOSTRING(oldrec - t), "]");
+		bprint(e.netname, "^3 improved their ", race_PlaceName(pos), " ^3place record with ", TIME_ENCODED_TOSTRING(t), recorddifference, "\n");
+	}
+	else if(oldname == "")
+		bprint(e.netname, "^2 set the ", race_PlaceName(pos), " ^2place record with ", TIME_ENCODED_TOSTRING(t), "\n");
+	else {
+		string recorddifference = strcat(" ^2[-", TIME_ENCODED_TOSTRING(oldrec - t), "]");
+		bprint(e.netname, "^2 broke ", oldname, "^2's ", race_PlaceName(pos), " ^2place, record ", strcat(TIME_ENCODED_TOSTRING(oldrec), " ^2with ", TIME_ENCODED_TOSTRING(t), recorddifference, "\n"));
+	}
+}
+
+void race_DeleteTime(float pos) {
+	float i;
+
+	for (i = pos-1; i <= RANKINGS_CNT-1; ++i) {
+		if (i == 0) {
+			db_put(ServerProgsDB, strcat(GetMapname(), rr, "time"), ftos(grecordtime[1]));
+			db_put(ServerProgsDB, strcat(GetMapname(), rr, "netname"), grecordholder[1]);
+			grecordtime[0] = grecordtime[1];
+			if (grecordholder[i])
+				strunzone(grecordholder[0]);
+			grecordholder[0] = strzone(grecordholder[1]);
+		}
+		else if (i == RANKINGS_CNT-1) {
+			db_put(ServerProgsDB, strcat(GetMapname(), rr, "time", ftos(i)), string_null);
+			db_put(ServerProgsDB, strcat(GetMapname(), rr, "netname", ftos(i)), string_null);
+			grecordtime[i] = 0;
+			if (grecordholder[i])
+				strunzone(grecordholder[i]);
+			grecordholder[i] = string_null;
+		}
+		else {
+			db_put(ServerProgsDB, strcat(GetMapname(), rr, "time", ftos(i)), ftos(grecordtime[i+1]));
+			db_put(ServerProgsDB, strcat(GetMapname(), rr, "netname", ftos(i)), grecordholder[i+1]);
+			grecordtime[i] = grecordtime[i+1];
+			if (grecordholder[i])
+				strunzone(grecordholder[i]);
+			grecordholder[i] = strzone(grecordholder[i+1]);
+		}
+	}
+
+	race_SendRankings(pos, 0, 1, MSG_ALL);
+	if(pos == 1)
+		race_send_recordtime(MSG_ALL);
+
+	if(rankings_reply)
+		strunzone(rankings_reply);
+	rankings_reply = strzone(getrankings());
+
+	worst_time = 0;
+}
+
 void race_SendTime(entity e, float cp, float t, float tvalid)
 {
 	float snew, l;
@@ -160,60 +367,25 @@
 				recordholder = "";
 
 			if(t != 0)
-			if(t < recordtime || recordtime == 0)
+			if(t < worst_time || worst_time == 0)
 			{
-				race_checkpoint_records[cp] = t;
-				if(race_checkpoint_recordholders[cp])
-					strunzone(race_checkpoint_recordholders[cp]);
-				race_checkpoint_recordholders[cp] = strzone(e.netname);
 				if(cp == race_timed_checkpoint)
 				{
-					float grecordtime;
-					string grecordholder, recorddifference;
-					string rr;
-					if(g_cts)
-						rr = CTS_RECORD;
-					else
-						rr = RACE_RECORD;
-					grecordtime = stof(db_get(ServerProgsDB, strcat(GetMapname(), rr, "time")));
-					grecordholder = db_get(ServerProgsDB, strcat(GetMapname(), rr, "netname"));
-					if(grecordholder == e.netname)
-						grecordholder = "";
-					if(grecordtime == 0)
-					{
-						bprint(e.netname, "^7 set the all-time fastest lap record with ", TIME_ENCODED_TOSTRING(t), "\n");
-						db_put(ServerProgsDB, strcat(GetMapname(), rr, "time"), ftos(t));
-						db_put(ServerProgsDB, strcat(GetMapname(), rr, "netname"), e.netname);
-						write_recordmarker(e, time - TIME_DECODE(t), TIME_DECODE(t));
-						race_send_recordtime(t, MSG_ALL);
-					}
-					else if(t < grecordtime)
-					{
-						recorddifference = strcat("^2", " [-", TIME_ENCODED_TOSTRING(grecordtime-t), "]");
-						if(grecordholder == "")
-							bprint(e.netname, strcat("^7 broke their all-time fastest lap record ", TIME_ENCODED_TOSTRING(grecordtime), " with ", TIME_ENCODED_TOSTRING(t), recorddifference), "\n");
-						else
-							bprint(e.netname, strcat("^7 broke ", grecordholder, "^7's all-time fastest lap record ", TIME_ENCODED_TOSTRING(grecordtime), " with ", TIME_ENCODED_TOSTRING(t), recorddifference), "\n");
-						db_put(ServerProgsDB, strcat(GetMapname(), rr, "time"), ftos(t));
-						db_put(ServerProgsDB, strcat(GetMapname(), rr, "netname"), e.netname);
-						write_recordmarker(e, time - TIME_DECODE(t), TIME_DECODE(t));
-						race_send_recordtime(t, MSG_ALL);
-					}
-					else
-					{
-						recorddifference = strcat("^1", " [+", TIME_ENCODED_TOSTRING(t-grecordtime), "]");
-						if(grecordholder == "")
-							bprint(e.netname, strcat("^7's new fastest lap ", TIME_ENCODED_TOSTRING(t), " could not break their all-time fastest lap record of ", TIME_ENCODED_TOSTRING(grecordtime), recorddifference), "\n");
-						else
-							bprint(e.netname, strcat("^7's new fastest lap ", TIME_ENCODED_TOSTRING(t), " could not break ", grecordholder, "^7's all-time fastest lap record of ", TIME_ENCODED_TOSTRING(grecordtime), recorddifference), "\n");
-					}
+					race_SetTime(e, t);
 				}
 
-				if(g_race_qualifying)
+				if(t < recordtime || recordtime == 0)
 				{
-					FOR_EACH_REALPLAYER(p)
-						if(p.race_checkpoint == cp)
-							race_SendNextCheckpoint(p, 0);
+					race_checkpoint_records[cp] = t;
+					if(race_checkpoint_recordholders[cp])
+						strunzone(race_checkpoint_recordholders[cp]);
+					race_checkpoint_recordholders[cp] = strzone(e.netname);
+					if(g_race_qualifying)
+					{
+						FOR_EACH_REALPLAYER(p)
+							if(p.race_checkpoint == cp)
+								race_SendNextCheckpoint(p, 0);
+					}
 				}
 			}
 		}



More information about the nexuiz-commits mailing list