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