case "revivals": if (!mode) return CTX(_("SCO^revivals")); else LOG_HELP(strcat("^3", "revivals", " ^7", _("Number of revivals")));
case "rounds": if (!mode) return CTX(_("SCO^rounds won")); else LOG_HELP(strcat("^3", "rounds", " ^7", _("Number of rounds won")));
case "score": if (!mode) return CTX(_("SCO^score")); else LOG_HELP(strcat("^3", "score", " ^7", _("Total score")));
+ case "avgspeed": if (!mode) return CTX(_("SCO^average speed"));else LOG_HELP(strcat("^3", "avgspeed", " ^7", _("Average speed (CTS)")));
+ case "topspeed": if (!mode) return CTX(_("SCO^top speed")); else LOG_HELP(strcat("^3", "topspeed", " ^7", _("Top speed (CTS)")));
case "startspeed": if (!mode) return CTX(_("SCO^start speed")); else LOG_HELP(strcat("^3", "startspeed", " ^7", _("Start speed (CTS)")));
case "strafe": if (!mode) return CTX(_("SCO^strafe")); else LOG_HELP(strcat("^3", "strafe", " ^7", _("Strafe efficiency (CTS)")));
case "suicides": if (!mode) return CTX(_("SCO^suicides")); else LOG_HELP(strcat("^3", "suicides", " ^7", _("Number of suicides")));
" +ctf/pickups +ctf/fckills +ctf/returns +ctf/caps +ons/takes +ons/caps" \
" +lms/lives +lms/rank" \
" +kh/kckills +kh/losses +kh/caps" \
-" ?+rc/laps ?+rc/time ?+cts/strafe ?+cts/startspeed +rc,cts/fastest" \
+" ?+rc/laps ?+rc/time ?+cts/strafe ?+cts/startspeed ?+cts/avgspeed ?+cts/topspeed +rc,cts/fastest" \
" +as/objectives +nb/faults +nb/goals" \
" +ka/pickups +ka/bckills +ka/bctime +ft/revivals" \
" +dom/ticks +dom/takes" \
return sprintf("%.2f qu/s", startspeed);
}
+ case SP_CTS_AVGSPEED:
+ {
+ float avgspeed = pl.(scores(field)) / 100;
+ if(avgspeed < 0) return "";
+ return sprintf("%.2f qu/s", avgspeed);
+ }
+
+ case SP_CTS_TOPSPEED:
+ {
+ float topspeed = pl.(scores(field)) / 100;
+ if(topspeed < 0) return "";
+ return sprintf("%.2f qu/s", topspeed);
+ }
+
default: case SP_SCORE:
tmp = pl.(scores(field));
f = scores_flags(field);
.float race_oldcheckpoint;
.bool startspeed_recorded;
.float startspeed;
+.float race_avgspeed_sum;
+.float race_avgspeed_time;
+.float race_avgspeed_best;
+.float race_topspeed;
+.float race_topspeed_best;
void havocbot_role_cts(entity this)
{
if(IS_DEAD(this))
if (g_race_qualifying) {
field(SP_CTS_STRAFE, "strafe", 0);
field(SP_CTS_STARTSPEED, "startspeed", 0);
+ field(SP_CTS_AVGSPEED, "avgspeed", 0);
+ field(SP_CTS_TOPSPEED, "topspeed", 0);
field(SP_RACE_FASTEST, "fastest", SFL_SORT_PRIO_PRIMARY | SFL_LOWER_IS_BETTER | SFL_TIME);
} else {
field(SP_RACE_LAPS, "laps", SFL_SORT_PRIO_PRIMARY);
}
}
player.strafe_efficiency_sum += calculate_strafe_efficiency(player, CS(player).movement, dt) * dt;
- if(!player.race_started) player.startspeed_recorded = false;
- if(player.race_started && !player.startspeed_recorded && player.race_checkpoint != 0 && player.race_oldcheckpoint == 0)
+ if(player.race_started)
{
- float new_startspeed = vlen(vec2(player.velocity));
- player.startspeed_recorded = true;
- if(new_startspeed > player.startspeed)
- {
- player.startspeed = new_startspeed;
- PlayerScore_Set(player, SP_CTS_STARTSPEED, player.startspeed * 100);
- }
+ if(!player.startspeed_recorded && player.race_checkpoint != 0 && player.race_oldcheckpoint == 0)
+ {
+ float new_startspeed = vlen(vec2(player.velocity));
+ player.startspeed_recorded = true;
+ if(new_startspeed > player.startspeed)
+ {
+ player.startspeed = new_startspeed;
+ PlayerScore_Set(player, SP_CTS_STARTSPEED, player.startspeed * 100);
+ }
+ }
+
+ float current_speed = vlen(vec2(player.velocity));
+ if(player.race_topspeed < current_speed)
+ {
+ player.race_topspeed = current_speed;
+ }
+ player.race_avgspeed_sum += current_speed * dt;
+ player.race_avgspeed_time += dt;
+ }
+ else
+ {
+ player.startspeed_recorded = false;
+ player.race_avgspeed_sum = player.race_avgspeed_time = player.race_topspeed = 0;
}
player.race_oldcheckpoint = player.race_checkpoint;
}
it.startspeed_recorded = false;
it.race_oldcheckpoint = 0;
PlayerScore_Set(it, SP_CTS_STARTSPEED, -1);
+ it.race_avgspeed_sum = it.race_avgspeed_time = it.race_topspeed = 0;
+ it.race_avgspeed_best = it.race_topspeed_best = -1;
+ PlayerScore_Set(it, SP_CTS_AVGSPEED, -1);
+ PlayerScore_Set(it, SP_CTS_TOPSPEED, -1);
if(it.race_place)
{
player.startspeed_recorded = false;
player.race_oldcheckpoint = 0;
PlayerScore_Set(player, SP_CTS_STARTSPEED, -1);
+ player.race_avgspeed_sum = player.race_avgspeed_time = player.race_topspeed = 0;
+ player.race_avgspeed_best = player.race_topspeed_best = -1;
+ PlayerScore_Set(player, SP_CTS_AVGSPEED, -1);
+ PlayerScore_Set(player, SP_CTS_TOPSPEED, -1);
race_SendAll(player, false);
}
frag_target.strafe_efficiency_sum = frag_target.strafe_efficiency_time = 0;
frag_target.startspeed_recorded = false;
+ frag_target.race_avgspeed_sum = frag_target.race_avgspeed_time = frag_target.race_topspeed = 0;
if(autocvar_g_cts_removeprojectiles)
{
PlayerScore_Set(player, SP_CTS_STRAFE, player.strafe_efficiency_best * 10000);
}
+ float race_speed_average = player.race_avgspeed_sum / player.race_avgspeed_time;
+ if(player.race_avgspeed_best < race_speed_average)
+ {
+ player.race_avgspeed_best = race_speed_average;
+ PlayerScore_Set(player, SP_CTS_AVGSPEED, player.race_avgspeed_best * 100);
+ }
+
+ if(player.race_topspeed_best < player.race_topspeed)
+ {
+ player.race_topspeed_best = player.race_topspeed;
+ PlayerScore_Set(player, SP_CTS_TOPSPEED, player.race_topspeed_best * 100);
+ }
+
// useful to prevent cheating by running back to the start line and starting out with more speed
if(autocvar_g_cts_finish_kill_delay)
ClientKill_Silent(player, autocvar_g_cts_finish_kill_delay);