From: Mario Date: Thu, 12 Jan 2017 15:18:11 +0000 (+1000) Subject: Add an option to show CTS-style capture time rankings in the CTF scoreboard X-Git-Tag: xonotic-v0.8.2~259^2~2 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=d80c5b9c3e8e3c9495201565991afc571f14a0e5;p=xonotic%2Fxonotic-data.pk3dir.git Add an option to show CTS-style capture time rankings in the CTF scoreboard --- diff --git a/gamemodes.cfg b/gamemodes.cfg index 9c70adca3..5e941f1c1 100644 --- a/gamemodes.cfg +++ b/gamemodes.cfg @@ -256,6 +256,7 @@ set g_ca_teams 0 set g_ctf 0 "Capture The Flag: take the enemy flag and bring it to yours at your base to score" set g_ctf_oneflag 0 "Allow oneflag CTF mode on maps that support it" set g_ctf_oneflag_reverse 0 "apply reverse mode to oneflag CTF (take flag to enemy bases to cap), overrides g_ctf_reverse only in oneflag, g_ctf_reverse still affects oneflag" +set g_ctf_leaderboard 0 "show top capture times in the scoreboard" set g_ctf_flag_return 1 "auto return the flag to base when touched by a teammate" set g_ctf_flag_return_carrying 0 "(manual return mode) auto return the flag to base if touched by a flag carrier" set g_ctf_flag_return_carried_radius 100 "allow flags to be returned by carrier if base is within this radius" diff --git a/qcsrc/client/hud/panel/scoreboard.qc b/qcsrc/client/hud/panel/scoreboard.qc index 35de2196b..6e2400ee6 100644 --- a/qcsrc/client/hud/panel/scoreboard.qc +++ b/qcsrc/client/hud/panel/scoreboard.qc @@ -1565,7 +1565,12 @@ void Scoreboard_Draw() pos = Scoreboard_MakeTable(pos, tm, panel_bg_color, bg_size); } - if(gametype == MAPINFO_TYPE_CTS || gametype == MAPINFO_TYPE_RACE) { + bool show_accuracy = (gametype != MAPINFO_TYPE_CTS && gametype != MAPINFO_TYPE_RACE && gametype != MAPINFO_TYPE_NEXBALL); + + if (show_accuracy && autocvar_hud_panel_scoreboard_accuracy && !warmup_stage) + pos = Scoreboard_AccuracyStats_Draw(pos, panel_bg_color, bg_size); + + if(gametype == MAPINFO_TYPE_CTS || gametype == MAPINFO_TYPE_RACE || (gametype == MAPINFO_TYPE_CTF && STAT(CTF_SHOWLEADERBOARD))) { if(race_speedaward) { drawcolorcodedstring(pos, sprintf(_("Speed award: %d%s ^7(%s^7)"), race_speedaward, race_speedaward_unit, race_speedaward_holder), hud_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL); pos.y += 1.25 * hud_fontsize.y; @@ -1576,8 +1581,6 @@ void Scoreboard_Draw() } pos = Scoreboard_Rankings_Draw(pos, playerslots[player_localnum], panel_bg_color, bg_size); } - else if (autocvar_hud_panel_scoreboard_accuracy && !warmup_stage && gametype != MAPINFO_TYPE_NEXBALL) - pos = Scoreboard_AccuracyStats_Draw(pos, panel_bg_color, bg_size); pos = Scoreboard_MapStats_Draw(pos, panel_bg_color, bg_size); diff --git a/qcsrc/common/stats.qh b/qcsrc/common/stats.qh index 3d21280e0..f14c9e717 100644 --- a/qcsrc/common/stats.qh +++ b/qcsrc/common/stats.qh @@ -119,6 +119,11 @@ REGISTER_STAT(ENTRAP_ORB, float) REGISTER_STAT(ENTRAP_ORB_ALPHA, float) REGISTER_STAT(ITEMSTIME, int, autocvar_sv_itemstime) +#ifdef SVQC +bool autocvar_g_ctf_leaderboard; +#endif +REGISTER_STAT(CTF_SHOWLEADERBOARD, bool, autocvar_g_ctf_leaderboard) + #ifdef SVQC int autocvar_g_multijump; float autocvar_g_multijump_add; diff --git a/qcsrc/common/util.qh b/qcsrc/common/util.qh index 05e4a4ea2..5211c7588 100644 --- a/qcsrc/common/util.qh +++ b/qcsrc/common/util.qh @@ -59,6 +59,7 @@ const float TIME_FACTOR = 100; #define TIME_ENCODED_TOSTRING(n) mmssss(n) #define RACE_RECORD "/race100record/" #define CTS_RECORD "/cts100record/" +#define CTF_RECORD "/ctf100record/" #define TIME_ENCODE(t) TIME_TO_NTHS(t, TIME_FACTOR) #define TIME_DECODE(n) ((n) / TIME_FACTOR) diff --git a/qcsrc/server/mutators/mutator/gamemode_ctf.qc b/qcsrc/server/mutators/mutator/gamemode_ctf.qc index 5ee07992f..147f16c4b 100644 --- a/qcsrc/server/mutators/mutator/gamemode_ctf.qc +++ b/qcsrc/server/mutators/mutator/gamemode_ctf.qc @@ -153,6 +153,9 @@ void ctf_CaptureRecord(entity flag, entity player) db_put(ServerProgsDB, strcat(GetMapname(), "/captimerecord/netname"), player.netname); write_recordmarker(player, (time - cap_time), cap_time); } + + if(autocvar_g_ctf_leaderboard && !ctf_oneflag) + race_setTime(GetMapname(), TIME_ENCODE(cap_time), player.crypto_idfp, player.netname, player, false); } bool ctf_Immediate_Return_Allowed(entity flag, entity toucher) @@ -2170,6 +2173,22 @@ MUTATOR_HOOKFUNCTION(ctf, ClientDisconnect) ctf_RemovePlayer(player); } +MUTATOR_HOOKFUNCTION(ctf, ClientConnect) +{ + if(!autocvar_g_ctf_leaderboard) + return; + + entity player = M_ARGV(0, entity); + + if(IS_REAL_CLIENT(player)) + { + for(int i = 1; i <= RANKINGS_CNT; ++i) + { + race_SendRankings(i, 0, 0, MSG_ONE); + } + } +} + MUTATOR_HOOKFUNCTION(ctf, PortalTeleport) { entity player = M_ARGV(0, entity); diff --git a/qcsrc/server/race.qc b/qcsrc/server/race.qc index a3cbc685f..48c8e32ae 100644 --- a/qcsrc/server/race.qc +++ b/qcsrc/server/race.qc @@ -26,31 +26,33 @@ void W_Porto_Fail(entity this, float failhard); float race_readTime(string map, float pos) { - string rr = (g_cts) ? CTS_RECORD : RACE_RECORD; + string rr = ((g_cts) ? CTS_RECORD : ((g_ctf) ? CTF_RECORD : RACE_RECORD)); return stof(db_get(ServerProgsDB, strcat(map, rr, "time", ftos(pos)))); } string race_readUID(string map, float pos) { - string rr = (g_cts) ? CTS_RECORD : RACE_RECORD; + string rr = ((g_cts) ? CTS_RECORD : ((g_ctf) ? CTF_RECORD : RACE_RECORD)); return db_get(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(pos))); } float race_readPos(string map, float t) { - float i; - for (i = 1; i <= RANKINGS_CNT; ++i) - if (race_readTime(map, i) == 0 || race_readTime(map, i) > t) - return i; + for(int i = 1; i <= RANKINGS_CNT; ++i) + { + int mytime = race_readTime(map, i); + if(!mytime || mytime > t) + return i; + } return 0; // pos is zero if unranked } void race_writeTime(string map, float t, string myuid) { - string rr = (g_cts) ? CTS_RECORD : RACE_RECORD; + string rr = ((g_cts) ? CTS_RECORD : ((g_ctf) ? CTF_RECORD : RACE_RECORD)); float newpos; newpos = race_readPos(map, t); @@ -87,7 +89,7 @@ void race_writeTime(string map, float t, string myuid) string race_readName(string map, float pos) { - string rr = (g_cts) ? CTS_RECORD : RACE_RECORD; + string rr = ((g_cts) ? CTS_RECORD : ((g_ctf) ? CTF_RECORD : RACE_RECORD)); return uid2name(db_get(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(pos)))); } @@ -244,15 +246,13 @@ void race_SendStatus(float id, entity e) }); } -void race_setTime(string map, float t, string myuid, string mynetname, entity e) +void race_setTime(string map, float t, string myuid, string mynetname, entity e, bool showmessage) { // netname only used TEMPORARILY for printing - float newpos, player_prevpos; - newpos = race_readPos(map, t); + int newpos = race_readPos(map, t); - float i; - player_prevpos = 0; - for(i = 1; i <= RANKINGS_CNT; ++i) + int player_prevpos = 0; + for(int i = 1; i <= RANKINGS_CNT; ++i) { if(race_readUID(map, i) == myuid) player_prevpos = i; @@ -264,7 +264,8 @@ void race_setTime(string map, float t, string myuid, string mynetname, entity e) { oldrec = race_readTime(GetMapname(), player_prevpos); race_SendStatus(0, e); // "fail" - Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_FAIL_RANKED, mynetname, player_prevpos, t, oldrec); + if(showmessage) + Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_FAIL_RANKED, mynetname, player_prevpos, t, oldrec); return; } else if (!newpos) @@ -272,7 +273,8 @@ void race_setTime(string map, float t, string myuid, string mynetname, entity e) // no ranking, time worse than the worst ranked oldrec = race_readTime(GetMapname(), RANKINGS_CNT); race_SendStatus(0, e); // "fail" - Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_FAIL_UNRANKED, mynetname, RANKINGS_CNT, t, oldrec); + if(showmessage) + Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_FAIL_UNRANKED, mynetname, RANKINGS_CNT, t, oldrec); return; } @@ -281,7 +283,8 @@ void race_setTime(string map, float t, string myuid, string mynetname, entity e) // if the player does not have a UID we can unfortunately not store the record, as the rankings system relies on UIDs if(myuid == "") { - Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_NEW_MISSING_UID, mynetname, t); + if(showmessage) + Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_NEW_MISSING_UID, mynetname, t); return; } @@ -291,7 +294,7 @@ void race_setTime(string map, float t, string myuid, string mynetname, entity e) // store new ranking race_writeTime(GetMapname(), t, myuid); - if (newpos == 1) + if (newpos == 1 && showmessage) { write_recordmarker(e, time - TIME_DECODE(t), TIME_DECODE(t)); race_send_recordtime(MSG_ALL); @@ -304,19 +307,22 @@ void race_setTime(string map, float t, string myuid, string mynetname, entity e) if(newpos == player_prevpos) { - Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_NEW_IMPROVED, mynetname, newpos, t, oldrec); + if(showmessage) + Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_NEW_IMPROVED, mynetname, newpos, t, oldrec); if(newpos == 1) { race_SendStatus(3, e); } // "new server record" else { race_SendStatus(1, e); } // "new time" } else if(oldrec == 0) { - Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_NEW_SET, mynetname, newpos, t); + if(showmessage) + Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_NEW_SET, mynetname, newpos, t); if(newpos == 1) { race_SendStatus(3, e); } // "new server record" else { race_SendStatus(2, e); } // "new rank" } else { - Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_NEW_BROKEN, mynetname, oldrec_holder, newpos, t, oldrec); + if(showmessage) + Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_NEW_BROKEN, mynetname, oldrec_holder, newpos, t, oldrec); if(newpos == 1) { race_SendStatus(3, e); } // "new server record" else { race_SendStatus(2, e); } // "new rank" } @@ -324,24 +330,20 @@ void race_setTime(string map, float t, string myuid, string mynetname, entity e) void race_deleteTime(string map, float pos) { - string rr; - if(g_cts) - rr = CTS_RECORD; - else - rr = RACE_RECORD; + string rr = ((g_cts) ? CTS_RECORD : ((g_ctf) ? CTF_RECORD : RACE_RECORD)); - float i; - for (i = pos; i <= RANKINGS_CNT; ++i) + for(int i = pos; i <= RANKINGS_CNT; ++i) { + string therank = ftos(i); if (i == RANKINGS_CNT) { - db_remove(ServerProgsDB, strcat(map, rr, "time", ftos(i))); - db_remove(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(i))); + db_remove(ServerProgsDB, strcat(map, rr, "time", therank)); + db_remove(ServerProgsDB, strcat(map, rr, "crypto_idfp", therank)); } else { - db_put(ServerProgsDB, strcat(map, rr, "time", ftos(i)), ftos(race_readTime(GetMapname(), i+1))); - db_put(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(i)), race_readUID(GetMapname(), i+1)); + db_put(ServerProgsDB, strcat(map, rr, "time", therank), ftos(race_readTime(GetMapname(), i+1))); + db_put(ServerProgsDB, strcat(map, rr, "crypto_idfp", therank), race_readUID(GetMapname(), i+1)); } } @@ -415,7 +417,7 @@ void race_SendTime(entity e, float cp, float t, float tvalid) { if(cp == race_timed_checkpoint) { - race_setTime(GetMapname(), t, e.crypto_idfp, e.netname, e); + race_setTime(GetMapname(), t, e.crypto_idfp, e.netname, e, true); MUTATOR_CALLHOOK(Race_FinalCheckpoint, e); } if(t < recordtime || recordtime == 0)