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