Merge branch 'terencehill/spectate_player' into 'master'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / hud / panel / racetimer.qc
1 #include "racetimer.qh"
2
3 #include <client/autocvars.qh>
4 #include <client/defs.qh>
5 #include <client/miscfunctions.qh>
6 #include <common/mapinfo.qh>
7
8 // Race timer (#6)
9
10 // return the string of the onscreen race timer
11 string MakeRaceString(int cp, float mytime, float theirtime, float othertime, float lapdelta, string theirname)
12 {
13         TC(int, cp);
14         string cpname, lapstr = "", timestr = "", col = "^7", othercol = "^7", othertimestr = "";
15         if(theirname == "" || !autocvar_cl_race_cptimes_showself)
16                 othertime = 0; // don't count personal time
17
18         if(theirtime == 0) // goal hit
19         {
20                 if(mytime > 0)
21                 {
22                         timestr = strcat("+", ftos_decimals(+mytime, TIME_DECIMALS));
23                         col = "^1";
24                 }
25                 else if(mytime == 0)
26                 {
27                         timestr = "+0.0";
28                         col = "^3";
29                 }
30                 else
31                 {
32                         timestr = strcat("-", ftos_decimals(-mytime, TIME_DECIMALS));
33                         col = "^2";
34                 }
35
36                 if(othertime > 0)
37                 {
38                         othertimestr = strcat("+", ftos_decimals(+othertime, TIME_DECIMALS));
39                         othercol = "^1";
40                 }
41                 else if(othertime == 0)
42                 {
43                         othertimestr = "+0.0";
44                         othercol = "^3";
45                 }
46                 else
47                 {
48                         othertimestr = strcat("-", ftos_decimals(-othertime, TIME_DECIMALS));
49                         othercol = "^2";
50                 }
51
52                 if(lapdelta > 0)
53                 {
54                         lapstr = sprintf(_(" (-%dL)"), lapdelta);
55                         col = "^2";
56                 }
57                 else if(lapdelta < 0)
58                 {
59                         lapstr = sprintf(_(" (+%dL)"), -lapdelta);
60                         col = "^1";
61                 }
62         }
63         else if(theirtime > 0) // anticipation
64         {
65                 if(mytime >= theirtime)
66                         timestr = strcat("+", ftos_decimals(mytime - theirtime, TIME_DECIMALS));
67                 else
68                         timestr = TIME_ENCODED_TOSTRING(TIME_ENCODE(theirtime));
69                 col = "^3";
70                 if(mytime >= othertime)
71                         othertimestr = strcat("+", ftos_decimals(mytime - othertime, TIME_DECIMALS));
72                 else
73                         othertimestr = TIME_ENCODED_TOSTRING(TIME_ENCODE(othertime));
74                 othercol = "^7";
75         }
76
77         if(cp == 254)
78                 cpname = _("Start line");
79         else if(cp == 255)
80                 cpname = _("Finish line");
81         else if(cp)
82                 cpname = sprintf(_("Intermediate %d"), cp);
83         else
84                 cpname = _("Finish line");
85
86         if(theirtime < 0)
87                 return strcat(col, cpname);
88         else if(theirname == "")
89                 return strcat(col, sprintf("%s (%s)", cpname, timestr));
90         else if(othertime)
91                 return strcat(col, sprintf("%s %s(%s)%s (%s %s)", cpname, othercol, othertimestr, col, timestr, strcat(ColorTranslateRGB(theirname), col, lapstr)));
92         else
93                 return strcat(col, sprintf("%s (%s %s)", cpname, timestr, strcat(ColorTranslateRGB(theirname), col, lapstr)));
94 }
95
96 void HUD_RaceTimer ()
97 {
98         if(!autocvar__hud_configure)
99         {
100                 if(!autocvar_hud_panel_racetimer) return;
101                 if(!(ISGAMETYPE(RACE) || ISGAMETYPE(CTS))) return;
102                 if(spectatee_status == -1) return;
103         }
104
105         HUD_Panel_LoadCvars();
106
107         vector pos, mySize;
108         pos = panel_pos;
109         mySize = panel_size;
110
111         if (autocvar_hud_panel_racetimer_dynamichud)
112                 HUD_Scale_Enable();
113         else
114                 HUD_Scale_Disable();
115         HUD_Panel_DrawBg();
116         if(panel_bg_padding)
117         {
118                 pos += '1 1 0' * panel_bg_padding;
119                 mySize -= '2 2 0' * panel_bg_padding;
120         }
121
122         // always force 4:1 aspect
123         vector newSize = '0 0 0';
124         if(mySize.x/mySize.y > 4)
125         {
126                 newSize.x = 4 * mySize.y;
127                 newSize.y = mySize.y;
128
129                 pos.x = pos.x + (mySize.x - newSize.x) / 2;
130         }
131         else
132         {
133                 newSize.y = 1/4 * mySize.x;
134                 newSize.x = mySize.x;
135
136                 pos.y = pos.y + (mySize.y - newSize.y) / 2;
137         }
138         mySize = newSize;
139
140         float a, t;
141         string s, forcetime;
142         vector str_pos;
143
144         if(autocvar__hud_configure)
145         {
146                 s = "0:13:37";
147                 draw_beginBoldFont();
148                 str_pos = pos + eX * 0.5 * (mySize.x - stringwidth(s, false, '1 1 0' * 0.6 * mySize.y));
149                 drawstring(str_pos, s, '1 1 0' * 0.6 * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
150                 draw_endBoldFont();
151                 s = strcat("^1", sprintf(_("Intermediate %d"), 1), " (+15.42)");
152                 str_pos = pos + vec2(0.5 * (mySize.x - stringwidth(s, true, '1 1 0' * 0.2 * mySize.y)), 0.6 * mySize.y);
153                 drawcolorcodedstring(str_pos, s, '1 1 0' * 0.2 * mySize.y, panel_fg_alpha, DRAWFLAG_NORMAL);
154                 s = sprintf(_("PENALTY: %.1f (%s)"), 2, _("missing a checkpoint"));
155                 s = strcat("^1", s);
156                 str_pos = pos + vec2(0.5 * (mySize.x - stringwidth(s, true, '1 1 0' * 0.2 * mySize.y)), 0.8 * mySize.y);
157                 drawcolorcodedstring(str_pos, s, '1 1 0' * 0.2 * mySize.y, panel_fg_alpha, DRAWFLAG_NORMAL);
158         }
159         else if(race_checkpointtime)
160         {
161                 a = bound(0, 2 - (time - race_checkpointtime), 1);
162                 s = "";
163                 forcetime = "";
164                 if(a > 0) // just hit a checkpoint?
165                 {
166                         if(race_checkpoint != 254)
167                         {
168                                 if(race_time && race_previousbesttime)
169                                         s = MakeRaceString(race_checkpoint, TIME_DECODE(race_time) - TIME_DECODE(race_previousbesttime), 0, ((race_mypreviousbesttime) ? TIME_DECODE(race_time) - TIME_DECODE(race_mypreviousbesttime) : 0), 0, race_previousbestname);
170                                 else
171                                         s = MakeRaceString(race_checkpoint, 0, -1, 0, 0, race_previousbestname);
172                                 if(race_time)
173                                         forcetime = TIME_ENCODED_TOSTRING(race_time);
174                         }
175                 }
176                 else
177                 {
178                         if(race_laptime && race_nextcheckpoint != 254)
179                         {
180                                 if(race_nextbesttime)
181                                 {
182                                         a = bound(0, 2 - ((race_laptime + TIME_DECODE(race_nextbesttime)) - (time + TIME_DECODE(race_penaltyaccumulator))), 1);
183                                         float a2 = ((race_mybesttime) ? bound(0, 2 - ((race_laptime + TIME_DECODE(race_mybesttime)) - (time + TIME_DECODE(race_penaltyaccumulator))), 1) : 0);
184                                         if(a > 0) // next one?
185                                                 s = MakeRaceString(race_nextcheckpoint, (time + TIME_DECODE(race_penaltyaccumulator)) - race_laptime, TIME_DECODE(race_nextbesttime), ((a2 > 0) ? TIME_DECODE(race_mybesttime) : 0), 0, race_nextbestname);
186                                 }
187                         }
188                 }
189
190                 if(s != "" && a > 0)
191                 {
192                         str_pos = pos + vec2(0.5 * (mySize.x - stringwidth(s, true, '1 1 0' * 0.2 * mySize.y)), 0.6 * mySize.y);
193                         drawcolorcodedstring(str_pos, s, '1 1 0' * 0.2 * mySize.y, panel_fg_alpha * a, DRAWFLAG_NORMAL);
194                 }
195
196                 if(race_penaltytime)
197                 {
198                         a = bound(0, 2 - (time - race_penaltyeventtime), 1);
199                         if(a > 0)
200                         {
201                                 s = sprintf(_("PENALTY: %.1f (%s)"), race_penaltytime * 0.1, race_penaltyreason);
202                                 s = strcat("^1", s);
203                                 str_pos = pos + vec2(0.5 * (mySize.x - stringwidth(s, true, '1 1 0' * 0.2 * mySize.y)), 0.8 * mySize.y);
204                                 drawcolorcodedstring(str_pos, s, '1 1 0' * 0.2 * mySize.y, panel_fg_alpha * a, DRAWFLAG_NORMAL);
205                         }
206                 }
207
208                 draw_beginBoldFont();
209
210                 if(forcetime != "")
211                 {
212                         a = bound(0, (time - race_checkpointtime) / 0.5, 1);
213                         str_pos = pos + eX * 0.5 * (mySize.x - stringwidth(forcetime, false, '1 1 0' * 0.6 * mySize.y));
214                         drawstring_expanding(str_pos, forcetime, '1 1 0' * 0.6 * mySize.y, '1 1 1', panel_fg_alpha, 0, a);
215                 }
216                 else
217                         a = 1;
218
219                 if(race_laptime && race_checkpoint != 255)
220                 {
221                         s = TIME_ENCODED_TOSTRING(TIME_ENCODE(time + TIME_DECODE(race_penaltyaccumulator) - race_laptime));
222                         str_pos = pos + eX * 0.5 * (mySize.x - stringwidth(s, false, '0.6 0.6 0' * mySize.y));
223                         drawstring(str_pos, s, '0.6 0.6 0' * mySize.y, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
224                 }
225
226                 draw_endBoldFont();
227         }
228         else
229         {
230                 if(race_mycheckpointtime)
231                 {
232                         a = bound(0, 2 - (time - race_mycheckpointtime), 1);
233                         s = MakeRaceString(race_mycheckpoint, TIME_DECODE(race_mycheckpointdelta), -(race_mycheckpointenemy == ""), 0, race_mycheckpointlapsdelta, race_mycheckpointenemy);
234                         str_pos = pos + vec2(0.5 * (mySize.x - stringwidth(s, true, '1 1 0' * 0.2 * mySize.y)), 0.6 * mySize.y);
235                         drawcolorcodedstring(str_pos, s, '1 1 0' * 0.2 * mySize.y, panel_fg_alpha * a, DRAWFLAG_NORMAL);
236                 }
237                 if(race_othercheckpointtime && race_othercheckpointenemy != "")
238                 {
239                         a = bound(0, 2 - (time - race_othercheckpointtime), 1);
240                         s = MakeRaceString(race_othercheckpoint, -TIME_DECODE(race_othercheckpointdelta), -(race_othercheckpointenemy == ""), 0, race_othercheckpointlapsdelta, race_othercheckpointenemy);
241                         str_pos = pos + vec2(0.5 * (mySize.x - stringwidth(s, true, '1 1 0' * 0.2 * mySize.y)), 0.6 * mySize.y);
242                         drawcolorcodedstring(str_pos, s, '1 1 0' * 0.2 * mySize.y, panel_fg_alpha * a, DRAWFLAG_NORMAL);
243                 }
244
245                 if(race_penaltytime && !race_penaltyaccumulator)
246                 {
247                         t = race_penaltytime * 0.1 + race_penaltyeventtime;
248                         a = bound(0, (1 + t - time), 1);
249                         if(a > 0)
250                         {
251                                 string col;
252                                 if(time < t)
253                                 {
254                                         t = (t - time) * 0.1;
255                                         col = "^1";
256                                 }
257                                 else
258                                 {
259                                         t = 0;
260                                         col = "^2";
261                                 }
262                                 s = sprintf(_("PENALTY: %.1f (%s)"), t, race_penaltyreason);
263                                 s = strcat(col, s);
264                                 str_pos = pos + vec2(0.5 * (mySize.x - stringwidth(s, true, '1 1 0' * 0.2 * mySize.y)), 0.6 * mySize.y);
265                                 drawcolorcodedstring(str_pos, s, '1 1 0' * 0.2 * mySize.y, panel_fg_alpha * a, DRAWFLAG_NORMAL);
266                         }
267                 }
268         }
269 }