1#include "announcer.qh"
2
3#include "mutators/events.qh"
4
5#include <common/notifications/all.qh>
6#include <common/stats.qh>
7
8bool announcer_1min;
9bool announcer_5min;
10string AnnouncerOption()
11{
12	string ret = autocvar_cl_announcer;
13	MUTATOR_CALLHOOK(AnnouncerOption, ret);
14	ret = M_ARGV(0, string);
15	return ret;
16}
17
18entity announcer_countdown;
19
20void Announcer_Countdown(entity this)
21{
22	float starttime = STAT(GAMESTARTTIME);
23	float roundstarttime = STAT(ROUNDSTARTTIME);
24	if(roundstarttime == -1)
25	{
26		Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_ROUNDSTOP);
27		delete(this);
28		announcer_countdown = NULL;
29		return;
30	}
31	if(roundstarttime >= starttime)
32		starttime = roundstarttime;
33	if(starttime <= time && roundstarttime != starttime) // game start time has passed
34		announcer_5min = announcer_1min = false; // reset maptime announcers now as well
35
36	float countdown = (starttime - time);
37	float countdown_rounded = floor(0.5 + countdown);
38
39	if(countdown <= 0) // countdown has finished, starttime is now
40	{
41		Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_BEGIN);
42		Local_Notification(MSG_MULTI, MULTI_COUNTDOWN_BEGIN);
43		delete(this);
44		announcer_countdown = NULL;
45		return;
46	}
47	else // countdown is still going
48	{
49		// if concomitant countdown to round start overrides countdown to game start
50		if(roundstarttime == starttime)
51		{
52			Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_ROUNDSTART, countdown_rounded);
53			Notification annce_num = Announcer_PickNumber(CNT_ROUNDSTART, countdown_rounded);
54			if(annce_num != NULL)
55				Local_Notification(MSG_ANNCE, annce_num);
56		}
57		else
58		{
59			Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_GAMESTART, countdown_rounded);
60			Notification annce_num = Announcer_PickNumber(CNT_GAMESTART, countdown_rounded);
61			if(annce_num != NULL)
62				Local_Notification(MSG_ANNCE, annce_num);
63		}
64
65		this.nextthink = (starttime - (countdown - 1));
66	}
67}
68
69/**
70 * Checks whether the server initiated a map restart (stat_game_starttime changed)
71 *
72 * TODO: Use a better solution where a common shared entitiy is used that contains
73 * timelimit, fraglimit and game_starttime! Requires engine changes (remove STAT_TIMELIMIT
74 * and STAT_FRAGLIMIT to be auto-sent)
75 */
76 float previous_game_starttime;
77void Announcer_Gamestart()
78{
79	float startTime = STAT(GAMESTARTTIME);
80	float roundstarttime = STAT(ROUNDSTARTTIME);
81	if(roundstarttime > startTime)
82		startTime = roundstarttime;
83	if(intermission)
84	{
85		if(announcer_countdown)
86		{
87			centerprint_kill(ORDINAL(CPID_ROUND));
88			if(announcer_countdown)
89			{
90				delete(announcer_countdown);
91				announcer_countdown = NULL;
92			}
93		}
94		return;
95	}
96
97	if(previous_game_starttime != startTime)
98	{
99		if(time < startTime)
100		{
101			if (!announcer_countdown)
102			{
103				announcer_countdown = new(announcer_countdown);
104				setthink(announcer_countdown, Announcer_Countdown);
105			}
106
107			if(time + 5.0 < startTime) // if connecting to server while restart was active don't always play prepareforbattle
108			if(time > announcer_countdown.nextthink) // don't play it again if countdown was already going
109				Local_Notification(MSG_ANNCE, ANNCE_PREPARE);
110
111			announcer_countdown.nextthink = startTime - floor(startTime - time); //synchronize nextthink to startTime
112		}
113	}
114
115	previous_game_starttime = startTime;
116}
117
118#define ANNOUNCER_CHECKMINUTE(minute) MACRO_BEGIN { \
119	if(announcer_##minute##min) { \
120		if(timeleft > minute * 60) \
121			announcer_##minute##min = false; \
122	} else { \
123		if(timeleft < minute * 60 && timeleft > minute * 60 - 1) { \
124			announcer_##minute##min = true; \
125			Local_Notification(MSG_ANNCE, ANNCE_REMAINING_MIN_##minute); \
126		} \
127	} \
128} MACRO_END
129
130void Announcer_Time()
131{
132	float timeleft;
133	if(warmup_stage)
134	{
135		float warmup_timelimit = STAT(WARMUP_TIMELIMIT);
136		if(warmup_timelimit > 0)
137			timeleft = max(0, warmup_timelimit - time);
138		else
139			timeleft = 0;
140	}
141	else
142		timeleft = max(0, STAT(TIMELIMIT) * 60 + STAT(GAMESTARTTIME) - time);
143
144	if(autocvar_cl_announcer_maptime >= 2)
145		ANNOUNCER_CHECKMINUTE(5);
146
147	if((autocvar_cl_announcer_maptime == 1) || (autocvar_cl_announcer_maptime == 3))
148		ANNOUNCER_CHECKMINUTE(1);
149}
150
151void Announcer()
152{
153	Announcer_Gamestart();
154	Announcer_Time();
155}
156