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