// legacy bot roles
.float race_checkpoint;
+.float race_oldcheckpoint;
+.bool startspeed_recorded;
+.float startspeed;
void havocbot_role_cts(entity this)
{
if(IS_DEAD(this))
GameRules_score_enabled(false);
GameRules_scoring(0, 0, 0, {
if (g_race_qualifying) {
+ field(SP_CTS_STRAFE, "strafe", 0);
+ field(SP_CTS_STARTSPEED, "startspeed", 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);
CS(player).movement_y = -M_SQRT1_2 * wishspeed;
}
}
+ player.strafe_efficiency_sum += calculate_strafe_efficiency(player, CS(player).movement);
+ if(!player.race_started) player.startspeed_recorded = false;
+ if(player.race_started && !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);
+ }
+ }
+ player.race_oldcheckpoint = player.race_checkpoint;
}
MUTATOR_HOOKFUNCTION(cts, reset_map_global)
PlayerScore_Sort(race_place, 0, true, false);
FOREACH_CLIENT(true, {
+ it.strafe_efficiency_best = -2;
+ PlayerScore_Set(it, SP_CTS_STRAFE, -20000);
+ it.startspeed_recorded = false;
+ it.race_oldcheckpoint = 0;
+ PlayerScore_Set(it, SP_CTS_STARTSPEED, -1);
+
if(it.race_place)
{
s = GameRules_scoring_add(it, RACE_FASTEST, 0);
race_PreparePlayer(player);
player.race_checkpoint = -1;
+ player.strafe_efficiency_sum = player.strafe_efficiency_tics = 0;
+ player.strafe_efficiency_best = -2;
+ PlayerScore_Set(player, SP_CTS_STRAFE, -20000);
+ player.startspeed_recorded = false;
+ player.race_oldcheckpoint = 0;
+ PlayerScore_Set(player, SP_CTS_STARTSPEED, -1);
race_SendAll(player, false);
}
frag_target.respawn_flags |= RESPAWN_FORCE;
race_AbandonRaceCheck(frag_target);
+ frag_target.strafe_efficiency_sum = frag_target.strafe_efficiency_tics = 0;
+ frag_target.startspeed_recorded = false;
+
if(autocvar_g_cts_removeprojectiles)
{
IL_EACH(g_projectiles, it.owner == frag_target && (it.flags & FL_PROJECTILE),
MUTATOR_HOOKFUNCTION(cts, Race_FinalCheckpoint)
{
entity player = M_ARGV(0, entity);
+ float strafe_efficiency_average = player.strafe_efficiency_sum / player.strafe_efficiency_tics;
+
+ if(player.strafe_efficiency_best < strafe_efficiency_average)
+ {
+ player.strafe_efficiency_best = strafe_efficiency_average;
+ PlayerScore_Set(player, SP_CTS_STRAFE, player.strafe_efficiency_best * 10000);
+ }
// useful to prevent cheating by running back to the start line and starting out with more speed
if(autocvar_g_cts_finish_kill_delay)