}
}
+void LocalCommand_print_cptimes(int request)
+{
+ switch(request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ LOG_HELP(_("Checkpoint times:"));
+ for (int i = 0; i <= 255; ++i)
+ {
+ if (race_checkpoint_splits[i])
+ LOG_HELP(race_checkpoint_splits[i]);
+ }
+ return;
+ }
+ default:
+ case CMD_REQUEST_USAGE:
+ {
+ LOG_HELP("Usage:^3 cl_cmd print_cptimes");
+ LOG_HELP(" No arguments required, will show current or last run checkpoint times.");
+ return;
+ }
+ }
+}
+
/* use this when creating a new command, making sure to place it in alphabetical order... also,
** ADD ALL NEW COMMANDS TO commands.cfg WITH PROPER ALIASES IN THE SAME FASHION!
void LocalCommand_(int request)
{
- switch(request)
- {
- case CMD_REQUEST_COMMAND:
- {
-
- return;
- }
-
- default:
- case CMD_REQUEST_USAGE:
- {
- LOG_HELP("Usage:^3 cl_cmd ");
- LOG_HELP(" No arguments required.");
- return;
- }
- }
+ switch(request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+
+ return;
+ }
+
+ default:
+ case CMD_REQUEST_USAGE:
+ {
+ LOG_HELP("Usage:^3 cl_cmd ");
+ LOG_HELP(" No arguments required.");
+ return;
+ }
+ }
}
*/
CLIENT_COMMAND(hud, "Commands regarding/controlling the HUD system") { LocalCommand_hud(request, arguments); }
CLIENT_COMMAND(localprint, "Create your own centerprint sent to yourself") { LocalCommand_localprint(request, arguments); }
CLIENT_COMMAND(mv_download, "Retrieve mapshot picture from the server") { LocalCommand_mv_download(request, arguments); }
+CLIENT_COMMAND(print_cptimes, "Print the stored checkpoint times for current or last run") { LocalCommand_print_cptimes(request); }
CLIENT_COMMAND(sendcvar, "Send a cvar to the server (like cl_weaponpriority)") { LocalCommand_sendcvar(request, arguments); }
void LocalCommand_macro_help()
#include "infomessages.qh"
+#include "racetimer.qh" // for race_checkpoint_splits
+#include <common/gamemodes/gamemode/race/race.qh> // for ISGAMETYPE(RACE)
#include <client/draw.qh>
#include <common/ent_cs.qh>
InfoMessage(s);
}
}
+ if(autocvar_cl_race_checkpoint_splits_hud && !spectatee_status) {
+ int lines[6];
+ int ln = 5;
+ // show up to race_nextcheckpoint (not including) or everything
+ // if you are before start (0 or 254)
+ // (except race_laptime != 0 for race, means next is
+ // start+finish so don't show previous lap finish)
+ int i;
+ if (race_checkpoint != 0 && race_checkpoint != 254)
+ { // middle of run/race
+ i = race_checkpoint;
+ }
+ else if (ISGAMETYPE(RACE) && race_nextcheckpoint == 0)
+ { // before start, but on race, so don't keep old finish visible
+ i = 253;
+ }
+ else
+ { // before start, not on race (cts), keep old run cps visible
+ i = 255;
+ }
+ for (; ln >= 0 && i >= 0; --i)
+ {
+ if (race_checkpoint_splits[i])
+ {
+ lines[ln] = i;
+ --ln;
+ }
+ }
+ for (int j = 0; j < 6; ++j)
+ InfoMessage(race_checkpoint_splits[lines[j]]);
+ }
}
else
{
#include <client/draw.qh>
#include <common/ent_cs.qh>
+// used for caching the string after passing through a checkpoint
+float racetimer_lastcheckpoint;
+string racetimer_checkpoint_comparison;
+string racetimer_checkpoint_time;
+bool racetimer_have_stored_splits;
+
// Race timer (#8)
void HUD_RaceTimer_Export(int fh)
return strcat(col, sprintf("%s (%s %s)", cpname, timestr, strcat(ColorTranslateRGB(theirname), col, lapstr)));
}
+void ClearRaceSplits() {
+ bool once = true;
+ racetimer_lastcheckpoint = 0;
+ for (int i = 0; i <= 255; ++i)
+ {
+ if(race_checkpoint_splits[i]
+ && autocvar_cl_race_checkpoint_splits_console)
+ {
+ if(once)
+ {
+ LOG_HELP(_("Checkpoint times:"));
+ once = false;
+ }
+ LOG_HELP(race_checkpoint_splits[i]);
+ }
+ strfree(race_checkpoint_splits[i]);
+ }
+ racetimer_have_stored_splits = false;
+}
+
+void StoreRaceSplits(float race_checkpoint, string forcetime, string s) {
+ // store checkpoint splits string for later printing
+ if (!entcs_IsSpectating(player_localnum))
+ {
+ // 0 or 255 go to 255 as finish, strcpy does the free if needed
+ strcpy(race_checkpoint_splits[race_checkpoint ? race_checkpoint : 255], (forcetime != "") ? sprintf("%s %s", forcetime, s) : s);
+ }
+
+ // cache
+ racetimer_lastcheckpoint = race_checkpoint;
+ strcpy(racetimer_checkpoint_comparison, s);
+ strcpy(racetimer_checkpoint_time, forcetime);
+ racetimer_have_stored_splits = true;
+}
+
void HUD_RaceTimer ()
{
if(!autocvar__hud_configure)
a = bound(0, 2 - (time - race_checkpointtime), 1);
s = "";
forcetime = "";
- if(a > 0) // just hit a checkpoint?
+ if(a > 0) // display a frozen split for the just reached checkpoint
{
- if(race_checkpoint != 254)
+ if(race_checkpoint != 254 && race_time != 0)
{
- if(race_time && race_previousbesttime)
- s = MakeRaceString(race_checkpoint, TIME_DECODE(race_time) - TIME_DECODE(race_previousbesttime), 0, ((race_mypreviousbesttime) ? TIME_DECODE(race_time) - TIME_DECODE(race_mypreviousbesttime) : 0), 0, race_previousbestname);
+ if (race_checkpoint == racetimer_lastcheckpoint)
+ {
+ // use cached strings
+ s = racetimer_checkpoint_comparison;
+ forcetime = racetimer_checkpoint_time;
+ }
else
- s = MakeRaceString(race_checkpoint, 0, -1, 0, 0, race_previousbestname);
- if(race_time)
- forcetime = TIME_ENCODED_TOSTRING(race_time, false);
-
- // store checkpoint splits string for later printing
- // check if we advanced to next cp
- if (!entcs_IsSpectating(player_localnum) && race_checkpoint_splits_previous != race_checkpoint)
{
- // are we somehow overwriting something? how?
- if (race_checkpoint_splits[race_checkpoint_splits_previous+1])
- {
- LOG_WARNF("race_checkpoint_splits: overwriting #%f %s\n",
- race_checkpoint_splits_previous+1,
- race_checkpoint_splits[race_checkpoint_splits_previous+1]);
- strfree(race_checkpoint_splits[race_checkpoint_splits_previous+1]);
- }
-
- strcpy(race_checkpoint_splits[race_checkpoint_splits_previous+1], sprintf("%s %s", forcetime, s));
+ // build checkpoint split strings
+ if(race_time && race_previousbesttime)
+ s = MakeRaceString(race_checkpoint, TIME_DECODE(race_time) - TIME_DECODE(race_previousbesttime), 0, ((race_mypreviousbesttime) ? TIME_DECODE(race_time) - TIME_DECODE(race_mypreviousbesttime) : 0), 0, race_previousbestname);
+ else
+ s = MakeRaceString(race_checkpoint, 0, -1, 0, 0, race_previousbestname);
+ if(race_time)
+ forcetime = TIME_ENCODED_TOSTRING(race_time, false);
- // don't use ++ in case that checkpoints have jumps like 10th to 20th
- race_checkpoint_splits_previous = race_checkpoint;
+ StoreRaceSplits(race_checkpoint, forcetime, s);
}
}
+ else
+ {
+ // clean cp splits on start
+ if(racetimer_have_stored_splits && race_time == 0)
+ ClearRaceSplits();
+ }
}
else
{
}
else
{
+ if(racetimer_have_stored_splits && (race_time == 0 || time < STAT(GAMESTARTTIME)))
+ ClearRaceSplits();
+
if(race_mycheckpointtime)
{
a = bound(0, 2 - (time - race_mycheckpointtime), 1);
float race_time;
float race_laptime;
float race_checkpointtime;
-string race_checkpoint_splits[255];
-int race_checkpoint_splits_previous = 0;
+string race_checkpoint_splits[256];
float race_previousbesttime;
float race_mypreviousbesttime;
string race_previousbestname;
race_penaltyaccumulator = 0;
race_laptime = time; // valid
}
-
- // show checkpoint splits after a run
- // specs can switch players for confusing splits, deny service
- // if hit 255 finish line or if finish line is 0 or if restarted
- if (!entcs_IsSpectating(player_localnum)
- && (race_checkpoint == 255
- || race_checkpoint < race_checkpoint_splits_previous))
- {
- LOG_HELP(_("Checkpoint times:"));
- for (int i = 0; i < 255; ++i)
- {
- // does this index have a split?
- if (race_checkpoint_splits[i])
- {
- // print it if enabled and free it
- if (autocvar_cl_race_checkpoint_splits_console)
- LOG_HELP(race_checkpoint_splits[i]);
- strfree(race_checkpoint_splits[i]);
- }
- }
-
- // allow registering 0th cp in case we start at 254 start line
- race_checkpoint_splits_previous = 0;
- }
break;
case RACE_NET_CHECKPOINT_CLEAR:
// or the release after it to support the old-stable release
// this can't be done now as players would lack these from their configs then
bool autocvar_cl_race_checkpoint_splits_console;
+bool autocvar_cl_race_checkpoint_splits_hud;
#else
AUTOCVAR_SAVE(cl_race_checkpoint_splits_console, bool, 1, "Print checkpoint splits to console");
+AUTOCVAR_SAVE(cl_race_checkpoint_splits_hud, bool, 1, "Show race checkpoint splits on HUD in infomessages");
#endif
bool autocvar_cl_race_cptimes_onlyself; // TODO: move to race gamemode
bool autocvar_cl_race_cptimes_showself = false;
seta cl_race_cptimes_showself 1 "Always show your own times as well as the current best on checkpoints in Race/CTS"
seta cl_race_cptimes_onlyself 0 "Only show your own times on checkpoints in Race/CTS. Can be forced on by the server via g_race_cptimes_onlyself"
seta cl_race_checkpoint_splits_console 1 "Print checkpoint splits to console"
+seta cl_race_checkpoint_splits_hud 1 "Show race checkpoint splits on HUD in infomessages"
seta cl_cts_noautoswitch 0 "Prevent forced switching to new weapons in CTS"