]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/client/hud/panel/physics.qc
take3: format 903 files
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / hud / panel / physics.qc
1 #include "physics.qh"
2
3 #include <client/autocvars.qh>
4 #include <client/defs.qh>
5 #include <client/miscfunctions.qh>
6 #include <client/main.qh>
7 #include <common/mapinfo.qh>
8 #include <lib/csqcmodel/cl_player.qh>
9
10 // Physics (#15)
11
12 vector acc_prevspeed;
13 float acc_prevtime, acc_avg, top_speed, top_speed_time;
14 float physics_update_time, discrete_speed, discrete_acceleration;
15 void HUD_Physics()
16 {
17         if (!autocvar__hud_configure) {
18                 if (!autocvar_hud_panel_physics) { return; }
19                 if (spectatee_status == -1 && (autocvar_hud_panel_physics == 1 || autocvar_hud_panel_physics == 3)) { return; }
20                 if (autocvar_hud_panel_physics == 3 && !(gametype == MAPINFO_TYPE_RACE || gametype == MAPINFO_TYPE_CTS)) { return; }
21         }
22
23         HUD_Panel_LoadCvars();
24
25         draw_beginBoldFont();
26
27         if (autocvar_hud_panel_physics_dynamichud) {
28                 HUD_Scale_Enable();
29         } else {
30                 HUD_Scale_Disable();
31         }
32         HUD_Panel_DrawBg();
33         if (panel_bg_padding) {
34                 panel_pos += '1 1 0' * panel_bg_padding;
35                 panel_size -= '2 2 0' * panel_bg_padding;
36         }
37
38         float acceleration_progressbar_scale = 0;
39         if (autocvar_hud_panel_physics_progressbar && autocvar_hud_panel_physics_acceleration_progressbar_scale > 1) {
40                 acceleration_progressbar_scale = autocvar_hud_panel_physics_acceleration_progressbar_scale;
41         }
42
43         float text_scale;
44         if (autocvar_hud_panel_physics_text_scale <= 0) {
45                 text_scale = 1;
46         } else {
47                 text_scale = min(autocvar_hud_panel_physics_text_scale, 1);
48         }
49
50         // compute speed
51         float speed, conversion_factor = GetSpeedUnitFactor(autocvar_hud_panel_physics_speed_unit);
52         string unit = GetSpeedUnit(autocvar_hud_panel_physics_speed_unit);
53         vector vel = (csqcplayer ? csqcplayer.velocity : pmove_vel);
54
55         float max_speed = floor(autocvar_hud_panel_physics_speed_max * conversion_factor + 0.5);
56         if (autocvar__hud_configure) {
57                 speed = floor(max_speed * 0.65 + 0.5);
58         } else if (autocvar_hud_panel_physics_speed_vertical) {
59                 speed = floor(vlen(vel) * conversion_factor + 0.5);
60         } else {
61                 speed = floor(vlen(vel - vel.z * '0 0 1') * conversion_factor + 0.5);
62         }
63
64         // compute acceleration
65         float acceleration, f;
66         if (autocvar__hud_configure) {
67                 acceleration = autocvar_hud_panel_physics_acceleration_max * 0.3;
68         } else {
69                 // 1 m/s = 0.0254 qu/s; 1 g = 9.80665 m/s^2
70                 f = time - acc_prevtime;
71                 if (autocvar_hud_panel_physics_acceleration_vertical) {
72                         acceleration = (vlen(vel) - vlen(acc_prevspeed));
73                 } else {
74                         acceleration = (vlen(vel - '0 0 1' * vel.z) - vlen(acc_prevspeed - '0 0 1' * acc_prevspeed.z));
75                 }
76
77                 acceleration = acceleration * (1 / max(0.0001, f)) * (0.0254 / 9.80665);
78
79                 acc_prevspeed = vel;
80                 acc_prevtime = time;
81
82                 if (autocvar_hud_panel_physics_acceleration_movingaverage) {
83                         f = bound(0, f * 10, 1);
84                         acc_avg = acc_avg * (1 - f) + acceleration * f;
85                         acceleration = acc_avg;
86                 }
87         }
88
89         const int acc_decimals = 2;
90         if (time > physics_update_time) {
91                 // workaround for ftos_decimals returning a negative 0
92                 if (discrete_acceleration > -1 / POW(10, acc_decimals) && discrete_acceleration < 0) {
93                         discrete_acceleration = 0;
94                 }
95                 discrete_acceleration = acceleration;
96                 discrete_speed = speed;
97                 physics_update_time += autocvar_hud_panel_physics_update_interval;
98                 if (physics_update_time < time) {
99                         physics_update_time = time + autocvar_hud_panel_physics_update_interval;
100                 }
101         }
102
103         // compute layout
104         float panel_ar = panel_size.x / panel_size.y;
105         vector speed_offset = '0 0 0', acceleration_offset = '0 0 0';
106         if (panel_ar >= 5 && !acceleration_progressbar_scale) {
107                 panel_size.x *= 0.5;
108                 if (autocvar_hud_panel_physics_flip) {
109                         speed_offset.x = panel_size.x;
110                 } else {
111                         acceleration_offset.x = panel_size.x;
112                 }
113         } else {
114                 panel_size.y *= 0.5;
115                 if (autocvar_hud_panel_physics_flip) {
116                         speed_offset.y = panel_size.y;
117                 } else {
118                         acceleration_offset.y = panel_size.y;
119                 }
120         }
121         int speed_baralign, acceleration_baralign;
122         if (autocvar_hud_panel_physics_baralign == 1) {
123                 acceleration_baralign = speed_baralign = 1;
124         } else if (autocvar_hud_panel_physics_baralign == 4) {
125                 acceleration_baralign = speed_baralign = 2;
126         } else if (autocvar_hud_panel_physics_flip) {
127                 acceleration_baralign = (autocvar_hud_panel_physics_baralign == 2);
128                 speed_baralign = (autocvar_hud_panel_physics_baralign == 3);
129         } else {
130                 speed_baralign = (autocvar_hud_panel_physics_baralign == 2);
131                 acceleration_baralign = (autocvar_hud_panel_physics_baralign == 3);
132         }
133         if (autocvar_hud_panel_physics_acceleration_progressbar_mode == 0) {
134                 acceleration_baralign = 3; // override hud_panel_physics_baralign value for acceleration
135         }
136         // draw speed
137         if (speed) {
138                 if (autocvar_hud_panel_physics_progressbar == 1 || autocvar_hud_panel_physics_progressbar == 2) {
139                         HUD_Panel_DrawProgressBar(panel_pos + speed_offset, panel_size, "progressbar", speed / max_speed, 0, speed_baralign, autocvar_hud_progressbar_speed_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
140                 }
141         }
142         vector tmp_offset = '0 0 0', tmp_size = '0 0 0';
143         if (autocvar_hud_panel_physics_text == 1 || autocvar_hud_panel_physics_text == 2) {
144                 tmp_size.x = panel_size.x * 0.75;
145                 tmp_size.y = panel_size.y * text_scale;
146                 if (speed_baralign) {
147                         tmp_offset.x = panel_size.x - tmp_size.x;
148                 }
149                 // else
150                 // tmp_offset_x = 0;
151                 tmp_offset.y = (panel_size.y - tmp_size.y) / 2;
152                 drawstring_aspect(panel_pos + speed_offset + tmp_offset, ftos(discrete_speed), tmp_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
153
154                 // draw speed unit
155                 if (speed_baralign) {
156                         tmp_offset.x = 0;
157                 } else {
158                         tmp_offset.x = tmp_size.x;
159                 }
160                 if (autocvar_hud_panel_physics_speed_unit_show) {
161                         // tmp_offset_y = 0;
162                         tmp_size.x = panel_size.x * (1 - 0.75);
163                         tmp_size.y = panel_size.y * 0.4 * text_scale;
164                         tmp_offset.y = (panel_size.y * 0.4 - tmp_size.y) / 2;
165                         drawstring_aspect(panel_pos + speed_offset + tmp_offset, unit, tmp_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
166                 }
167         }
168
169         // compute and draw top speed
170         if (autocvar_hud_panel_physics_topspeed) {
171                 if (autocvar_hud_panel_physics_text == 1 || autocvar_hud_panel_physics_text == 2) {
172                         if (autocvar__hud_configure) {
173                                 top_speed = floor(max_speed * 0.75 + 0.5);
174                                 f = 1;
175                         } else {
176                                 if (speed >= top_speed) {
177                                         top_speed = speed;
178                                         top_speed_time = time;
179                                 }
180                                 if (top_speed != 0) {
181                                         f = max(1, autocvar_hud_panel_physics_topspeed_time);
182                                         // divide by f to make it start from 1
183                                         f = cos(((time - top_speed_time) / f) * PI / 2);
184                                 } else { // hide top speed 0, it would be stupid
185                                         f = 0;
186                                 }
187                         }
188                         if (f > 0) {
189                                 // top speed progressbar peak
190                                 if (speed < top_speed) {
191                                         if (autocvar_hud_panel_physics_progressbar == 1 || autocvar_hud_panel_physics_progressbar == 2) {
192                                                 float peak_offsetX;
193                                                 vector peak_size = '0 0 0';
194                                                 if (speed_baralign == 0) {
195                                                         peak_offsetX = min(top_speed, max_speed) / max_speed * panel_size.x;
196                                                 } else if (speed_baralign == 1) {
197                                                         peak_offsetX = (1 - min(top_speed, max_speed) / max_speed) * panel_size.x;
198                                                 } else { // if (speed_baralign == 2)
199                                                         peak_offsetX = min(top_speed, max_speed) / max_speed * panel_size.x * 0.5;
200                                                 }
201                                                 peak_size.x = floor(panel_size.x * 0.01 + 1.5);
202                                                 peak_size.y = panel_size.y;
203                                                 if (speed_baralign == 2) { // draw two peaks, on both sides
204                                                         drawfill(panel_pos + speed_offset + eX * (0.5 * panel_size.x + peak_offsetX - peak_size.x), peak_size, autocvar_hud_progressbar_speed_color, f * autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
205                                                         drawfill(panel_pos + speed_offset + eX * (0.5 * panel_size.x - peak_offsetX + peak_size.x), peak_size, autocvar_hud_progressbar_speed_color, f * autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
206                                                 } else {
207                                                         drawfill(panel_pos + speed_offset + eX * (peak_offsetX - peak_size.x), peak_size, autocvar_hud_progressbar_speed_color, f * autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
208                                                 }
209                                         }
210                                 }
211
212                                 // top speed
213                                 tmp_offset.y = panel_size.y * 0.4;
214                                 tmp_size.x = panel_size.x * (1 - 0.75);
215                                 tmp_size.y = (panel_size.y - tmp_offset.y) * text_scale;
216                                 tmp_offset.y += (panel_size.y - tmp_offset.y - tmp_size.y) / 2;
217                                 drawstring_aspect(panel_pos + speed_offset + tmp_offset, ftos(top_speed), tmp_size, '1 0 0', f * panel_fg_alpha, DRAWFLAG_NORMAL);
218                         } else {
219                                 top_speed = 0;
220                         }
221                 }
222         }
223
224         // draw acceleration
225         if (acceleration) {
226                 if (autocvar_hud_panel_physics_progressbar == 1 || autocvar_hud_panel_physics_progressbar == 3) {
227                         vector progressbar_color;
228                         if (acceleration < 0) {
229                                 progressbar_color = autocvar_hud_progressbar_acceleration_neg_color;
230                         } else {
231                                 progressbar_color = autocvar_hud_progressbar_acceleration_color;
232                         }
233
234                         f = acceleration / autocvar_hud_panel_physics_acceleration_max;
235                         if (autocvar_hud_panel_physics_acceleration_progressbar_nonlinear) {
236                                 f = (f >= 0 ? sqrt(f) : -sqrt(-f));
237                         }
238
239                         if (acceleration_progressbar_scale) { // allow progressbar to go out of panel bounds
240                                 tmp_size = acceleration_progressbar_scale * panel_size.x * eX + panel_size.y * eY;
241
242                                 if (acceleration_baralign == 1) {
243                                         tmp_offset.x = panel_size.x - tmp_size.x;
244                                 } else if (acceleration_baralign == 2 || acceleration_baralign == 3) {
245                                         tmp_offset.x = (panel_size.x - tmp_size.x) / 2;
246                                 } else {
247                                         tmp_offset.x = 0;
248                                 }
249                                 tmp_offset.y = 0;
250                         } else {
251                                 tmp_size = panel_size;
252                                 tmp_offset = '0 0 0';
253                         }
254
255                         HUD_Panel_DrawProgressBar(panel_pos + acceleration_offset + tmp_offset, tmp_size, "accelbar", f, 0, acceleration_baralign, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
256                 }
257         }
258
259         if (autocvar_hud_panel_physics_text == 1 || autocvar_hud_panel_physics_text == 3) {
260                 tmp_size.x = panel_size.x;
261                 tmp_size.y = panel_size.y * text_scale;
262                 tmp_offset.x = 0;
263                 tmp_offset.y = (panel_size.y - tmp_size.y) / 2;
264
265                 drawstring_aspect(panel_pos + acceleration_offset + tmp_offset, strcat(ftos_decimals(discrete_acceleration, acc_decimals), "g"), tmp_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
266         }
267
268         draw_endBoldFont();
269 }