Add proximity-based map record reminders

This commit is contained in:
2026-10-17 21:54:13 -04:00
parent 6781a4ed5a
commit c19bef6dc6
11 changed files with 738 additions and 32 deletions
+86 -1
View File
@@ -1,4 +1,4 @@
/* tws_t5_leaderboard.gsc - private map record announcements and .leaders replay. */
/* tws_t5_leaderboard.gsc - private map records, round reminders and .leaders replay. */
#include maps\_utility;
#include common_scripts\utility;
@@ -24,10 +24,12 @@ init()
level.tws_lb_pending = undefined;
level.tws_lb_cache = undefined;
level.tws_lb_attempt = 0;
level.tws_lb_chase_finished = undefined;
scripts\sp\tws_t5_common::register_help_command(".leaders", "Show the map record again");
scripts\sp\tws_t5_common::register_connect_handler(::lb_welcome);
level thread lb_chat_listener();
level thread lb_worker();
level thread lb_round_watcher();
}
lb_worker()
@@ -64,6 +66,88 @@ lb_worker()
}
}
lb_round_watcher()
{
level endon("end_game");
level endon("game_ended");
level endon("intermission");
last_round = 0;
for (;;)
{
// T6 advances its counter before the between-round pause is over.
// Both engines notify the actual start; never synthesize a late start.
level waittill("start_of_round");
if (!isDefined(level.round_number) || level.round_number <= last_round)
continue;
last_round = level.round_number;
lb_round_start(last_round);
}
}
lb_round_start(round)
{
if (isDefined(level.tws_lb_chase_finished))
return;
snapshot = lb_cached_record();
if (!isDefined(snapshot) || snapshot.round < 2)
return;
message = lb_round_message(round, snapshot.round);
if (message == "")
return;
// Celebrate at most once, even if a later refresh raises the fleet record.
// Busy clients skip the milestone too; no delayed mid-round announcements.
if (round > snapshot.round)
level.tws_lb_chase_finished = true;
players = getPlayers();
for (i = 0; i < players.size; i++)
players[i] lb_remind_player(snapshot, message);
}
lb_round_message(round, record)
{
if (round < 1 || record < 2)
return "";
gap = record - round;
if (gap < 0)
return "Recorded high round passed!";
if (gap == 0)
return "Record round reached!";
if (gap > 20)
return "";
// Anchor the cadence to the target, not to round numbers divisible by 5/2.
if (gap > 10 && gap % 5 != 0)
return "";
if (gap > 5 && gap <= 10 && gap % 2 != 0)
return "";
if (gap == 1)
return "1 round away from matching it";
return gap + " rounds away from matching it";
}
lb_player_ready(player)
{
// A welcome attempt (even with no record) or manual request releases this
// gate. Give that full announcement at least 30 seconds before a reminder.
if (!isDefined(player.tws_lb_last_request) ||
getTime() - player.tws_lb_last_request < 30000)
return false;
if (!isDefined(player.sessionstate) ||
(player.sessionstate != "playing" && player.sessionstate != "spectator"))
return false;
if (isDefined(player.hasSpawned) && !player.hasSpawned)
return false;
return true;
}
lb_remind_player(snapshot, message)
{
if (!lb_player_ready(self))
return;
self scripts\sp\tws_t5_common::show_record_reminder(snapshot, message);
}
lb_welcome()
{
self endon("disconnect");
@@ -128,6 +212,7 @@ lb_request(manual)
// This also applies when the cache is unavailable.
if (manual)
self notify("tws_lb_requested");
self.tws_lb_last_request = getTime();
snapshot = lb_cached_record();
if (!isDefined(snapshot) && !manual)
return;