Draw: purge SELFPARAM
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / announcer.qc
1 #include "announcer.qh"
2 #include "_all.qh"
3
4 #include "../common/notifications.qh"
5 #include "../common/stats.qh"
6 #include "../common/util.qh"
7
8 bool announcer_1min;
9 bool announcer_5min;
10 void Announcer_Countdown()
11 {
12         SELFPARAM();
13         float starttime = getstatf(STAT_GAMESTARTTIME);
14         float roundstarttime = getstatf(STAT_ROUNDSTARTTIME);
15         if(roundstarttime == -1)
16         {
17                 Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_ROUNDSTOP);
18                 remove(this);
19                 return;
20         }
21         if(roundstarttime >= starttime)
22                 starttime = roundstarttime;
23         if(starttime <= time && roundstarttime != starttime) // game start time has passed
24                 announcer_5min = announcer_1min = false; // reset maptime announcers now as well
25
26         float countdown = (starttime - time);
27         float countdown_rounded = floor(0.5 + countdown);
28
29         if(countdown <= 0) // countdown has finished, starttime is now
30         {
31                 Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_BEGIN);
32                 Local_Notification(MSG_MULTI, MULTI_COUNTDOWN_BEGIN);
33                 remove(this);
34                 return;
35         }
36         else // countdown is still going
37         {
38                 // if concomitant countdown to round start overrides countdown to game start
39                 if(roundstarttime == starttime)
40                 {
41                         Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_ROUNDSTART, countdown_rounded);
42                         Local_Notification(MSG_ANNCE, Announcer_PickNumber(CNT_ROUNDSTART, countdown_rounded));
43                 }
44                 else
45                 {
46                         Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_GAMESTART, countdown_rounded);
47                         Local_Notification(MSG_ANNCE, Announcer_PickNumber(CNT_GAMESTART, countdown_rounded));
48                 }
49
50                 this.nextthink = (starttime - (countdown - 1));
51         }
52 }
53
54 /**
55  * Checks whether the server initiated a map restart (stat_game_starttime changed)
56  *
57  * TODO: Use a better solution where a common shared entitiy is used that contains
58  * timelimit, fraglimit and game_starttime! Requires engine changes (remove STAT_TIMELIMIT
59  * and STAT_FRAGLIMIT to be auto-sent)
60  */
61  float previous_game_starttime;
62 void Announcer_Gamestart()
63 {
64         float startTime = getstatf(STAT_GAMESTARTTIME);
65         float roundstarttime = getstatf(STAT_ROUNDSTARTTIME);
66         if(roundstarttime > startTime)
67                 startTime = roundstarttime;
68
69         if(previous_game_starttime != startTime)
70         {
71                 if(time < startTime)
72                 {
73                         entity e = find(world, classname, "announcer_countdown");
74                         if (!e)
75                         {
76                                 e = spawn();
77                                 e.classname = "announcer_countdown";
78                                 e.think = Announcer_Countdown;
79                         }
80
81                         if(time + 5.0 < startTime) // if connecting to server while restart was active don't always play prepareforbattle
82                         if(time > e.nextthink) // don't play it again if countdown was already going
83                                 Local_Notification(MSG_ANNCE, ANNCE_PREPARE);
84
85                         e.nextthink = startTime - floor(startTime - time); //synchronize nextthink to startTime
86                 }
87         }
88
89         previous_game_starttime = startTime;
90 }
91
92
93 // Plays the 1 minute or 5 minutes (of maptime) remaining sound, if client wants it
94 void Announcer_Time()
95 {
96         float timelimit = getstatf(STAT_TIMELIMIT);
97         float timeleft = max(0, timelimit * 60 + getstatf(STAT_GAMESTARTTIME) - time);
98         float warmup_timeleft = 0;
99
100         if(warmup_stage)
101                 if(autocvar_g_warmup_limit > 0)
102                         warmup_timeleft = max(0, autocvar_g_warmup_limit + getstatf(STAT_GAMESTARTTIME) - time);
103
104         // 5 minute check
105         if(autocvar_cl_announcer_maptime >= 2)
106         {
107                 // make sure that after connect (and e.g. 4 minutes left) we will not get a wrong sound
108                 if(announcer_5min)
109                 {
110                         if(((!warmup_stage || autocvar_g_warmup_limit == 0) && timeleft > 300)
111                                 || (warmup_stage && autocvar_g_warmup_limit > 0 && warmup_timeleft > 300))
112                                         announcer_5min = false;
113                 }
114                 else
115                 {
116                         if(((!warmup_stage || autocvar_g_warmup_limit == 0) && timelimit > 0 && timeleft < 300 && timeleft > 299)
117                                 || (warmup_stage && autocvar_g_warmup_limit > 0 && warmup_timeleft < 300 && warmup_timeleft > 299))
118                         {
119                                 //if we're in warmup mode, check whether there's a warmup timelimit
120                                 if(!(autocvar_g_warmup_limit == -1 && warmup_stage))
121                                 {
122                                         announcer_5min = true;
123                                         Local_Notification(MSG_ANNCE, ANNCE_REMAINING_MIN_5);
124                                 }
125                         }
126                 }
127         }
128
129         // 1 minute check
130         if((autocvar_cl_announcer_maptime == 1) || (autocvar_cl_announcer_maptime == 3))
131         {
132                 if (announcer_1min)
133                 {
134                         if(((!warmup_stage || autocvar_g_warmup_limit == 0) && timeleft > 60)
135                                 || (warmup_stage && autocvar_g_warmup_limit > 0 && warmup_timeleft > 60))
136                                         announcer_1min = false;
137                 }
138                 else if(((!warmup_stage || autocvar_g_warmup_limit == 0) && timelimit > 0 && timeleft < 60)
139                         || (warmup_stage && autocvar_g_warmup_limit > 0 && warmup_timeleft < 60))
140                 {
141                         // if we're in warmup mode, check whether there's a warmup timelimit
142                         if(!(autocvar_g_warmup_limit == -1 && warmup_stage))
143                         {
144                                 announcer_1min = true;
145                                 Local_Notification(MSG_ANNCE, ANNCE_REMAINING_MIN_1);
146                         }
147                 }
148         }
149 }
150
151 void Announcer()
152 {
153         Announcer_Gamestart();
154         Announcer_Time();
155 }