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>
13 float acc_prevtime, acc_avg, top_speed, top_speed_time;
14 float physics_update_time, discrete_speed, discrete_acceleration;
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; }
23 HUD_Panel_LoadCvars();
27 if (autocvar_hud_panel_physics_dynamichud) {
33 if (panel_bg_padding) {
34 panel_pos += '1 1 0' * panel_bg_padding;
35 panel_size -= '2 2 0' * panel_bg_padding;
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;
44 if (autocvar_hud_panel_physics_text_scale <= 0) {
47 text_scale = min(autocvar_hud_panel_physics_text_scale, 1);
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);
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);
61 speed = floor(vlen(vel - vel.z * '0 0 1') * conversion_factor + 0.5);
64 // compute acceleration
65 float acceleration, f;
66 if (autocvar__hud_configure) {
67 acceleration = autocvar_hud_panel_physics_acceleration_max * 0.3;
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));
74 acceleration = (vlen(vel - '0 0 1' * vel.z) - vlen(acc_prevspeed - '0 0 1' * acc_prevspeed.z));
77 acceleration = acceleration * (1 / max(0.0001, f)) * (0.0254 / 9.80665);
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;
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;
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;
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) {
108 if (autocvar_hud_panel_physics_flip) {
109 speed_offset.x = panel_size.x;
111 acceleration_offset.x = panel_size.x;
115 if (autocvar_hud_panel_physics_flip) {
116 speed_offset.y = panel_size.y;
118 acceleration_offset.y = panel_size.y;
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);
130 speed_baralign = (autocvar_hud_panel_physics_baralign == 2);
131 acceleration_baralign = (autocvar_hud_panel_physics_baralign == 3);
133 if (autocvar_hud_panel_physics_acceleration_progressbar_mode == 0) {
134 acceleration_baralign = 3; // override hud_panel_physics_baralign value for acceleration
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);
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;
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);
155 if (speed_baralign) {
158 tmp_offset.x = tmp_size.x;
160 if (autocvar_hud_panel_physics_speed_unit_show) {
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);
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);
176 if (speed >= top_speed) {
178 top_speed_time = time;
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
189 // top speed progressbar peak
190 if (speed < top_speed) {
191 if (autocvar_hud_panel_physics_progressbar == 1 || autocvar_hud_panel_physics_progressbar == 2) {
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;
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);
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);
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);
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;
231 progressbar_color = autocvar_hud_progressbar_acceleration_color;
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));
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;
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;
251 tmp_size = panel_size;
252 tmp_offset = '0 0 0';
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);
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;
263 tmp_offset.y = (panel_size.y - tmp_size.y) / 2;
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);