Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
view.qc
Go to the documentation of this file.
1#include "view.qh"
2
3#include <client/announcer.qh>
5#include <client/draw.qh>
6#include <client/hud/_mod.qh>
9#include <client/mapvoting.qh>
11#include <client/shownames.qh>
12#include <common/anim.qh>
13#include <common/animdecide.qh>
14#include <common/constants.qh>
16#include <common/debug.qh>
17#include <common/ent_cs.qh>
20#include <common/mapinfo.qh>
28#include <common/net_linked.qh>
29#include <common/net_notice.qh>
31#include <common/stats.qh>
32#include <common/teams.qh>
34#include <common/viewloc.qh>
37#include <common/wepent.qh>
42
45
50
58
65
66#define avg_factor(avg_time) (1 - exp(-frametime / max(0.001, avg_time)))
67
68#define lowpass(value, frac, ref_store, ret) \
69 ret = ref_store = ref_store * (1 - frac) + (value) * frac;
70
71#define lowpass_limited(value, frac, limit, ref_store, ret) MACRO_BEGIN \
72 float __ignore; lowpass(value, frac, ref_store, __ignore); \
73 ret = ref_store = bound((value) - (limit), ref_store, (value) + (limit)); \
74MACRO_END
75
76#define highpass(value, frac, ref_store, ret) MACRO_BEGIN \
77 float __f = 0; lowpass(value, frac, ref_store, __f); \
78 ret = (value) - __f; \
79MACRO_END
80
81#define highpass_limited(value, frac, limit, ref_store, ret) MACRO_BEGIN \
82 float __f = 0; lowpass_limited(value, frac, limit, ref_store, __f); \
83 ret = (value) - __f; \
84MACRO_END
85
86#define lowpass2(value, frac, ref_store, ref_out) MACRO_BEGIN \
87 lowpass(value.x, frac, ref_store.x, ref_out.x); \
88 lowpass(value.y, frac, ref_store.y, ref_out.y); \
89MACRO_END
90
91#define highpass2(value, frac, ref_store, ref_out) MACRO_BEGIN \
92 highpass(value.x, frac, ref_store.x, ref_out.x); \
93 highpass(value.y, frac, ref_store.y, ref_out.y); \
94MACRO_END
95
96#define highpass2_limited(value, frac, limit, ref_store, ref_out) MACRO_BEGIN \
97 highpass_limited(value.x, frac, limit, ref_store.x, ref_out.x); \
98 highpass_limited(value.y, frac, limit, ref_store.y, ref_out.y); \
99MACRO_END
100
101#define lowpass3(value, frac, ref_store, ref_out) MACRO_BEGIN \
102 lowpass(value.x, frac, ref_store.x, ref_out.x); \
103 lowpass(value.y, frac, ref_store.y, ref_out.y); \
104 lowpass(value.z, frac, ref_store.z, ref_out.z); \
105MACRO_END
106
107#define highpass3(value, frac, ref_store, ref_out) MACRO_BEGIN \
108 highpass(value.x, frac, ref_store.x, ref_out.x); \
109 highpass(value.y, frac, ref_store.y, ref_out.y); \
110 highpass(value.z, frac, ref_store.z, ref_out.z); \
111MACRO_END
112
114{
116 return; // cl_followmodel_ofs already calculated for this frame
117
118 float frac;
119 vector gunorg = '0 0 0';
120 static vector vel_average;
121 static vector gunorg_adjustment_highpass;
122 static vector gunorg_adjustment_lowpass;
123
124 vector vel;
126 vel = view.velocity;
127 else
128 {
129 vector forward, right, up;
130 MAKE_VECTORS(view_angles, forward, right, up);
131 vel.x = view.velocity * forward;
132 vel.y = view.velocity * right * -1;
133 vel.z = view.velocity * up;
134 }
135
136 vel.x = bound(vel_average.x - autocvar_cl_followmodel_limit, vel.x, vel_average.x + autocvar_cl_followmodel_limit);
137 vel.y = bound(vel_average.y - autocvar_cl_followmodel_limit, vel.y, vel_average.y + autocvar_cl_followmodel_limit);
138 vel.z = bound(vel_average.z - autocvar_cl_followmodel_limit, vel.z, vel_average.z + autocvar_cl_followmodel_limit);
139
141 lowpass3(vel, frac, vel_average, gunorg);
142
143 gunorg *= -autocvar_cl_followmodel_speed * 0.042;
144
145 // perform highpass/lowpass on the adjustment vectors (turning velocity into acceleration!)
146 // trick: we must do the lowpass LAST, so the lowpass vector IS the final vector!
148 highpass3(gunorg, frac, gunorg_adjustment_highpass, gunorg);
150 lowpass3(gunorg, frac, gunorg_adjustment_lowpass, gunorg);
151
153 {
154 vector fixed_gunorg;
155 vector forward, right, up;
156 MAKE_VECTORS(view_angles, forward, right, up);
157 fixed_gunorg.x = gunorg * forward;
158 fixed_gunorg.y = gunorg * right * -1;
159 fixed_gunorg.z = gunorg * up;
160 gunorg = fixed_gunorg;
161 }
162
163 cl_followmodel_ofs = gunorg;
165}
166
168{
169 float frac;
170 vector gunangles = '0 0 0';
171 static vector gunangles_prev = '0 0 0';
172 static vector gunangles_highpass = '0 0 0';
173 static vector gunangles_adjustment_highpass;
174 static vector gunangles_adjustment_lowpass;
175
176 if (view.csqcmodel_teleported)
177 gunangles_prev = view_angles;
178
179 // in the highpass, we _store_ the DIFFERENCE to the actual view angles...
180 gunangles_highpass += gunangles_prev;
181 PITCH(gunangles_highpass) += 360 * floor((PITCH(view_angles) - PITCH(gunangles_highpass)) / 360 + 0.5);
182 YAW(gunangles_highpass) += 360 * floor((YAW(view_angles) - YAW(gunangles_highpass)) / 360 + 0.5);
183 ROLL(gunangles_highpass) += 360 * floor((ROLL(view_angles) - ROLL(gunangles_highpass)) / 360 + 0.5);
185 highpass2_limited(view_angles, frac, autocvar_cl_leanmodel_limit, gunangles_highpass, gunangles);
186 gunangles_prev = view_angles;
187 gunangles_highpass -= gunangles_prev;
188
189 PITCH(gunangles) *= -autocvar_cl_leanmodel_speed;
190 YAW(gunangles) *= -autocvar_cl_leanmodel_speed;
191
192 // we assume here: PITCH = 0, YAW = 1, ROLL = 2
194 highpass2(gunangles, frac, gunangles_adjustment_highpass, gunangles);
196 lowpass2(gunangles, frac, gunangles_adjustment_lowpass, gunangles);
197
198 gunangles.x = -gunangles.x; // pitch was inverted, now that actually matters
199
200 return gunangles;
201}
202
204{
205 bool clonground = !(view.anim_implicit_state & ANIMIMPLICITSTATE_INAIR);
206 static bool oldonground;
207 static float hitgroundtime;
208 if (clonground)
209 {
210 float f = time; // cl.movecmd[0].time
211 if (!oldonground)
212 hitgroundtime = f;
213 }
214 oldonground = clonground;
215
216 // calculate for swinging gun model
217 // the gun bobs when running on the ground, but doesn't bob when you're in the air.
218 vector gunorg = '0 0 0';
219 static float bobmodel_scale = 0;
220 static float time_ofs = 0; // makes the effect always restart in the same way
221 static float avg_xyspeed = 0; // makes the effect always restart in the same way
222 if (clonground)
223 {
224 if (time - hitgroundtime > 0.05)
225 bobmodel_scale = min(1, bobmodel_scale + frametime * 5);
226 }
227 else
228 bobmodel_scale = max(0, bobmodel_scale - frametime * 5);
229
230 if (bobmodel_scale)
231 {
232 float xyspeed = bound(0, vlen(vec2(view.velocity)), 400);
233 // smooth speed changes to get rid of weapon stuttering on direction changes
234 const float avg_time = 0.1;
235 float frac = 1 - exp(-frametime / max(0.001, avg_time));
236 avg_xyspeed = frac * xyspeed + (1 - frac) * avg_xyspeed;
237 // stop bobbing at a very low value of avg_xyspeed instead of 0
238 // since the averaging formula takes a very long time to reach exactly 0
239 if (avg_xyspeed < 1)
240 time_ofs = time;
241 else
242 {
243 if (avg_xyspeed < 400) // reduce bob frequency too when player walks crouching
244 time_ofs += frametime * map_bound_ranges(avg_xyspeed, 150, 400, 0.08, 0);
245
246 float bspeed = avg_xyspeed * 0.01 * bobmodel_scale;
247 float s = (time - time_ofs) * autocvar_cl_bobmodel_speed;
248 gunorg.y = bspeed * autocvar_cl_bobmodel_side * sin(s);
249 gunorg.z = bspeed * autocvar_cl_bobmodel_up * cos(s * 2);
250 }
251 }
252 else
253 time_ofs = time;
254
255 return gunorg;
256}
257
259{
260 if (autocvar_chase_active || STAT(HEALTH) <= 0) return;
261
263
265 {
268 }
269
271 this.angles += leanmodel_ofs(view);
272
273 // vertical view bobbing code
274 // TODO: cl_bob
275
276 // horizontal view bobbing code
277 // TODO: cl_bob2
278
279 // fall bobbing code
280 // causes the view to swing down and back up when touching the ground
281 // TODO: cl_bobfall
282
283 // gun model bobbing code
285 this.origin += bobmodel_ofs(view);
286}
287
291
292.string name_last;
293
295{
296 // alpha calculations
299 float a = (amin >= amax) ? amax : bound(amin, this.m_alpha, amax);
300
301 int mask = (intermission || (STAT(HEALTH) <= 0) || autocvar_chase_active) ? 0 : MASK_NORMAL;
302 int wepskin = this.m_skin;
303 bool invehicle = player_localentnum > maxclients;
304 if (invehicle) a = -1;
305 Weapon wep = this.activeweapon;
307 vector g = weaponentity_glowmod(wep, c, this);
309 int fx = ((me.csqcmodel_effects & EFMASK_CHEAP)
311 &~ (EF_FULLBRIGHT); // can mask team color, so get rid of it
312 for (entity e = this; e; e = e.weaponchild)
313 {
314 e.drawmask = mask;
315 e.alpha = a;
316 e.skin = wepskin;
317 e.colormap = 256 + c; // colormap == 0 is black, c == 0 is white
318 e.glowmod = g;
319 e.csqcmodel_effects = fx;
321 }
322 if(a >= 0)
323 {
324 string name = wep.mdl;
325 string newname = wep.wr_viewmodel(wep, this);
326 if(newname)
327 name = newname;
328 bool swap = name != this.name_last;
329 // if (swap)
330 {
331 this.name_last = name;
332 CL_WeaponEntity_SetModel(this, name, swap);
334 }
335 anim_update(this);
336 if ((!this.animstate_override && !this.animstate_looping) || time > this.animstate_endtime)
337 anim_set(this, this.anim_idle, true, false, false);
338 }
339 float f = 0; // 0..1; 0: fully active
340 float rate = STAT(WEAPONRATEFACTOR);
341 float eta = rate ? ((this.weapon_nextthink - time) / rate) : 0;
342 if (eta <= 0) f = this.weapon_eta_last;
343 else switch (this.state)
344 {
345 case WS_RAISE:
346 {
347 f = eta / max(eta, this.weapon_switchdelay);
348 break;
349 }
350 case WS_DROP:
351 {
352 f = 1 - eta / max(eta, this.weapon_switchdelay);
353 break;
354 }
355 case WS_CLEAR:
356 {
357 f = 1;
358 break;
359 }
360 }
361 this.weapon_eta_last = f;
362 this.angles_x = (-90 * f * f);
363 viewmodel_animate(this);
364 MUTATOR_CALLHOOK(DrawViewModel, this);
365 setorigin(this, this.origin);
366}
367
368STATIC_INIT(viewmodel) {
369 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
370 viewmodels[slot] = new(viewmodel);
371}
372
374{
375 vec = cs_project(vec);
376 return vec;
377}
378
380{
381 return screen_pos.z >= 0
382 && screen_pos.x >= 0
383 && screen_pos.y >= 0
384 && screen_pos.x < vid_conwidth
385 && screen_pos.y < vid_conheight;
386}
387
394
397
399{
400 if(!STAT(SHOWFPS))
401 return;
402
403 float currentTime = gettime(GETTIME_FRAMESTART);
404
406 if(currentTime - showfps_prevfps_time > STAT(SHOWFPS))
407 {
408 float fps = showfps_framecounter / (currentTime - showfps_prevfps_time);
410 showfps_prevfps_time = currentTime;
411
412 int channel = MSG_C2S;
413 WriteHeader(channel, fpsreport);
414 WriteShort(channel, bound(0, rint(fps), 32767)); // prevent insane fps values
415 }
416}
417
418STATIC_INIT(fpscounter_init)
419{
420 float currentTime = gettime(GETTIME_FRAMESTART);
421 showfps_prevfps_time = currentTime; // we must initialize it to avoid an instant low frame sending
422}
423
424bool IsZooming(bool ignore_spectatorbutton_zoom)
425{
426 bool zoomdir = button_zoom;
427
429 for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
430 {
431 entity wepent = viewmodels[slot];
432 if (wepent.switchweapon != wepent.activeweapon)
433 continue;
434 Weapon wep = wepent.activeweapon;
435 if (wep != WEP_Null && wep.wr_zoomdir)
436 if (wep.wr_zoomdir(wep)) // TODO: merge this with wr_zoom?
437 zoomdir = true;
438 }
439
440 if (!ignore_spectatorbutton_zoom)
442 zoomdir = !zoomdir;
443
444 return zoomdir;
445}
446
447const float MAX_ZOOMFACTOR = 30;
450void ZoomScroll(float nPrimary)
451{
452 bool zoomin = (nPrimary == K_MWHEELUP);
454 zoomin = !zoomin;
455
456 // allow negatives so that players can scroll the other way, biggest change allowed is +100%
457 float zoomscroll_scale = 1 + min(fabs(autocvar_cl_zoomscroll_scale), 1);
458
459 if (zoomin)
461 else
463}
464
465bool View_InputEvent(int bInputType, float nPrimary, float nSecondary)
466{
467 if (bInputType == 2 || bInputType == 3)
468 return false;
469
470 // at this point bInputType can only be 0 or 1 (key pressed or released)
471 bool key_pressed = (bInputType == 0);
472
473 if (nPrimary == K_MWHEELUP || nPrimary == K_MWHEELDOWN)
474 {
476 return false; // zoom scroll disabled
477 if (!IsZooming(true))
478 return false;
479 if (key_pressed)
480 ZoomScroll(nPrimary);
481 return true;
482 }
483
484 return false;
485}
486
489{
490 float zoomsensitivity, zoomspeed, zoomfactor, zoomdir;
491 float velocityzoom, curspeed;
492 vector v;
493
494 zoomdir = IsZooming(false);
495
496 zoomspeed = autocvar_cl_zoomspeed;
497 if(zoomspeed >= 0 && (zoomspeed < 0.5 || zoomspeed > 16))
498 zoomspeed = 3.5;
499 zoomsensitivity = autocvar_cl_zoomsensitivity;
500
501 zoomfactor = autocvar_cl_zoomfactor;
502 if(zoomfactor < 1 || zoomfactor > MAX_ZOOMFACTOR)
503 zoomfactor = 2.5;
504
505 if(zoomdir)
506 zoomin_effect = 0;
507
508 if (spectatee_status > 0 && STAT(CAMERA_SPECTATOR) == 2)
510 else if (camera_active)
513 {
514 float spawnzoomfactor = bound(1, autocvar_cl_spawnzoom_factor, MAX_ZOOMFACTOR);
515
517 current_viewzoom = bound(1 / spawnzoomfactor, current_viewzoom, 1);
518 if(current_viewzoom == 1)
519 zoomin_effect = 0;
520 }
521 else
522 {
524 {
525 // initialize zoom scroll in the first frame / reset zoom scroll when fully zoomed out
526 if (!zoomscroll_factor || (current_viewzoom == 1 && !zoomdir))
527 {
528 zoomscroll_factor_target = zoomfactor;
529 zoomscroll_factor = zoomfactor;
530 }
532 {
535 else if (autocvar_cl_zoomscroll_speed != 0)
536 {
537 // NOTE: this averaging formula is frametime independent
538 float avg_time = 1 / autocvar_cl_zoomscroll_speed;
539 float frac = 1 - exp(-drawframetime / max(0.001, avg_time));
541 }
542 }
543 zoomfactor = zoomscroll_factor;
544 }
545
546 if(zoomspeed < 0) // instant zoom
547 {
548 if(zoomdir)
549 current_viewzoom = 1 / zoomfactor;
550 else
552 }
553 else
554 {
555 if(zoomdir)
556 current_viewzoom = 1 / bound(1, 1 / current_viewzoom + drawframetime * zoomspeed * (zoomfactor - 1), zoomfactor);
557 else
558 current_viewzoom = bound(1 / zoomfactor, current_viewzoom + drawframetime * zoomspeed * (1 - 1 / zoomfactor), 1);
559 }
560 }
561
562 if(zoomfactor == 1 || current_viewzoom > 0.999) // zoomfactor check prevents a division by 0
564 else if(almost_equals(current_viewzoom, 1/zoomfactor))
566 else
567 current_zoomfraction = (current_viewzoom - 1) / (1/zoomfactor - 1);
568
569 if(zoomsensitivity < 1)
570 setsensitivityscale(current_viewzoom ** (1 - zoomsensitivity));
571 else
572 setsensitivityscale(1);
573
574 if(autocvar_cl_velocityzoom_enabled && autocvar_cl_velocityzoom_type && !autocvar_cl_lockview) // _type = 0 disables velocity zoom too
575 {
576 if (intermission || (spectatee_status > 0 && STAT(CAMERA_SPECTATOR) == 2))
577 curspeed = 0;
578 else
579 {
580 vector forward, right, up;
581 MAKE_VECTORS(view_angles, forward, right, up);
582 v = pmove_vel;
583 if(csqcplayer)
584 v = csqcplayer.velocity;
585
587 {
588 case 3: curspeed = max(0, forward * v); break;
589 case 2: curspeed = (forward * v); break;
590 case 1: default: curspeed = vlen(v); break;
591 }
592 }
593
594 velocityzoom = bound(0, drawframetime / max(0.000000001, autocvar_cl_velocityzoom_time), 1); // speed at which the zoom adapts to player velocity
595 avgspeed = avgspeed * (1 - velocityzoom) + (curspeed / autocvar_cl_velocityzoom_speed) * velocityzoom;
596 velocityzoom = exp(float2range11(avgspeed * -autocvar_cl_velocityzoom_factor / 1) * 1);
597
598 //print(ftos(avgspeed), " avgspeed, ", ftos(curspeed), " curspeed, ", ftos(velocityzoom), " return\n"); // for debugging
599 }
600 else
601 velocityzoom = 1;
602
603 float frustumx, frustumy, fovx, fovy;
604 frustumy = tan(fov * (M_PI / 360)) * 0.75 * current_viewzoom * velocityzoom;
605 frustumx = frustumy * vid_width / vid_height / vid_pixelheight;
606 fovx = atan2(frustumx, 1) * (360 / M_PI);
607 fovy = atan2(frustumy, 1) * (360 / M_PI);
608
609 return '1 0 0' * fovx + '0 1 0' * fovy;
610}
611
613{
614 float frustumy = tan(fov * (M_PI / 360)) * 0.75;
615 float frustumx = frustumy * vid_width / vid_height / vid_pixelheight;
616 float fovx = atan2(frustumx, 1) * (360 / M_PI);
617 float fovy = atan2(frustumy, 1) * (360 / M_PI);
618 return '1 0 0' * fovx + '0 1 0' * fovy;
619}
620
622{
623 float fovx, fovy;
624 float width = (ov_worldmax.x - ov_worldmin.x);
625 float height = (ov_worldmax.y - ov_worldmin.y);
626 float distance_to_middle_of_world = vlen(ov_mid - ov_org);
627 fovx = atan2(width/2, distance_to_middle_of_world) / M_PI * 360.0;
628 fovy = atan2(height/2, distance_to_middle_of_world) / M_PI * 360.0;
629 return '1 0 0' * fovx + '0 1 0' * fovy;
630}
631
632// this function must match W_SetupShot!
633
635
637const float CAMERA_FREE = 1;
638const float CAMERA_CHASE = 2;
640
643
646
649
651
654
656{
657 static int waiting_CAMERA_SPECTATOR_update;
658 static bool camera_spectator_3rd_person;
659 if(spectatee_status > 0)
660 {
662 {
663 // if chase_active is enabled by the user, spectator camera never switches to 1st person
664 // that means CAMERA_SPECTATOR 1 behaves as 0 and is redundant, so we forcedly skip it
665 if (STAT(CAMERA_SPECTATOR) == 1)
666 {
667 if (!waiting_CAMERA_SPECTATOR_update)
668 {
669 Impulse_Send(IMP_weapon_drop); // switch to CAMERA_SPECTATOR 2
670 waiting_CAMERA_SPECTATOR_update = 1;
671 }
672 }
673 else waiting_CAMERA_SPECTATOR_update = 0;
674 camera_spectator_3rd_person = true;
675 }
676
677 // chase_active disabled by the user?
678 if(camera_spectator_3rd_person && autocvar_chase_active == 0)
679 {
680 if (STAT(CAMERA_SPECTATOR) >= 1)
681 {
682 if (waiting_CAMERA_SPECTATOR_update != STAT(CAMERA_SPECTATOR))
683 {
684 Impulse_Send(IMP_weapon_drop); // switch to CAMERA_SPECTATOR (2 and) 0
685 waiting_CAMERA_SPECTATOR_update = STAT(CAMERA_SPECTATOR);
686 }
687 }
688 else
689 {
690 waiting_CAMERA_SPECTATOR_update = 0;
691 camera_spectator_3rd_person = false;
692 }
693 return true;
694 }
695 }
696
697 if(autocvar_chase_active <= 0) // greater than 0 means it's enabled manually, and this code is skipped
698 {
699 if(STAT(CAMERA_SPECTATOR))
700 {
701 if(spectatee_status > 0)
702 {
703 if(!camera_spectator_3rd_person)
704 {
705 cvar_set("chase_active", "-2");
706 camera_spectator_3rd_person = true;
707 return true;
708 }
709 }
710 else if(camera_spectator_3rd_person)
711 {
712 cvar_set("chase_active", "0");
713 camera_spectator_3rd_person = false;
714 }
715
716 if(autocvar_chase_active == -2)
717 return true;
718 }
719 else if(camera_spectator_3rd_person)
720 {
721 cvar_set("chase_active", "0");
722 camera_spectator_3rd_person = false;
723 }
724 }
725 return false;
726}
727
730int WantEventchase(entity this, bool want_vehiclechase)
731{
733 return 0;
734 if(STAT(GAME_STOPPED) || intermission)
735 return 1;
736 if(this.viewloc)
737 return 1;
738 if(spectatee_status >= 0)
739 {
740 if(want_vehiclechase)
741 return 1;
743 return 1;
744 if(autocvar_cl_eventchase_frozen && StatusEffects_active(STATUSEFFECT_Frozen, this))
745 return 1;
746 if(autocvar_cl_eventchase_death && (STAT(HEALTH) <= 0))
747 {
749 {
750 // don't stop eventchase once it's started (even if velocity changes afterwards)
751 if(this.velocity == '0 0 0' || eventchase_running)
752 return 1;
753 }
754 else return 1;
755 }
757 {
759 return 1;
760 else if (eventchase_running)
761 return -1; // disable chase_active while eventchase is still enabled so to avoid a glicth
762 }
763 }
764 return 0;
765}
766
768{
769 // event chase camera
770 if(autocvar_chase_active <= 0) // greater than 0 means it's enabled manually, and this code is skipped
771 {
772 bool vehicle_chase = (hud != HUD_NORMAL && (autocvar_cl_eventchase_vehicle || spectatee_status > 0));
773
774 float vehicle_viewdist = 0;
775 vector vehicle_viewofs = '0 0 0';
776
777 if(vehicle_chase)
778 {
780 {
781 Vehicle info = REGISTRY_GET(Vehicles, hud);
782 vehicle_viewdist = info.height;
783 vehicle_viewofs = info.view_ofs;
784 if(vehicle_viewdist < 0) // when set below 0, this vehicle doesn't use third person view (gunner slots)
785 vehicle_chase = false;
786 }
787 else
788 vehicle_chase = false;
789 }
790
791 int eventchase = WantEventchase(this, vehicle_chase);
792 if (eventchase)
793 {
794 vector current_view_origin_override = '0 0 0';
795 vector view_offset_override = '0 0 0';
796 float chase_distance_override = 0;
797 bool custom_eventchase = MUTATOR_CALLHOOK(CustomizeEventchase, this);
798 if(custom_eventchase)
799 {
800 current_view_origin_override = M_ARGV(0, vector);
801 view_offset_override = M_ARGV(1, vector);
802 chase_distance_override = M_ARGV(0, float);
803 }
804 eventchase_running = true;
805
806 // make special vector since we can't use view_origin (It is one frame old as of this code, it gets set later with the results this code makes.)
807 vector current_view_origin = (csqcplayer ? csqcplayer.origin : pmove_org);
808 if (custom_eventchase)
809 current_view_origin = current_view_origin_override;
810
811 // detect maximum viewoffset and use it
813 if(vehicle_chase)
814 {
815 if(vehicle_viewofs)
816 view_offset = vehicle_viewofs;
817 else
819 }
820 if (custom_eventchase)
821 view_offset = view_offset_override;
822
823 if(view_offset)
824 {
825 WarpZone_TraceLine(current_view_origin, current_view_origin + view_offset + ('0 0 1' * autocvar_cl_eventchase_maxs.z), MOVE_WORLDONLY, this);
826 if(trace_fraction == 1) { current_view_origin += view_offset; }
827 else { current_view_origin.z += max(0, (trace_endpos.z - current_view_origin.z) - autocvar_cl_eventchase_maxs.z); }
828 }
829
830 // We must enable chase_active to get a third person view (weapon viewmodel hidden and own player model showing).
831 // Ideally, there should be another way to enable third person cameras, such as through setproperty()
832 // -1 enables chase_active while marking it as set by this code, and not by the user (which would be 1)
833 if(!autocvar_chase_active) { cvar_set("chase_active", "-1"); }
834
835 // make the camera smooth back
836 float chase_distance = autocvar_cl_eventchase_distance;
837 if(vehicle_chase)
838 {
839 if(vehicle_viewofs)
840 chase_distance = vehicle_viewdist;
841 else
843 }
844 if (custom_eventchase)
845 chase_distance = chase_distance_override;
846
848 eventchase_current_distance += autocvar_cl_eventchase_speed * (chase_distance - eventchase_current_distance) * frametime; // slow down the further we get
849 else if(eventchase_current_distance != chase_distance)
850 eventchase_current_distance = chase_distance;
851
852 vector forward, right, up;
853 MAKE_VECTORS(view_angles, forward, right, up);
854
855 vector eventchase_target_origin = (current_view_origin - (forward * eventchase_current_distance));
856 WarpZone_TraceBox(current_view_origin, autocvar_cl_eventchase_mins, autocvar_cl_eventchase_maxs, eventchase_target_origin, MOVE_WORLDONLY, this);
857
858 // If the boxtrace fails, revert back to line tracing.
859 if(!this.viewloc)
861 {
862 eventchase_target_origin = (current_view_origin - (forward * eventchase_current_distance));
863 WarpZone_TraceLine(current_view_origin, eventchase_target_origin, MOVE_WORLDONLY, this);
864 setproperty(VF_ORIGIN, (trace_endpos - (forward * autocvar_cl_eventchase_mins.z)));
865 }
866 else { setproperty(VF_ORIGIN, trace_endpos); }
867
868 if(!this.viewloc)
870 }
871
872 if (eventchase <= 0 && autocvar_chase_active < 0) // time to disable chase_active if it was set by this code
873 {
874 eventchase_running = false;
875 cvar_set("chase_active", "0");
876 eventchase_current_distance = 0; // start from 0 next time
877 }
878 }
879 // workaround for camera stuck between player's legs when using chase_active 1
880 // because the engine stops updating the chase_active camera when the game ends
881 else if(intermission)
882 {
883 cvar_settemp("chase_active", "-1");
885 }
886}
887
889
891{
892 // accumulate damage with each stat update
893 static float damage_total_prev = 0;
894 float damage_total = STAT(HITSOUND_DAMAGE_DEALT_TOTAL);
895 float unaccounted_damage_new = COMPARE_INCREASING(damage_total, damage_total_prev);
896 damage_total_prev = damage_total;
897
898 static float damage_dealt_time_prev = 0;
899 float damage_dealt_time = STAT(HIT_TIME);
900 if (damage_dealt_time != damage_dealt_time_prev)
901 {
902 unaccounted_damage += unaccounted_damage_new;
903 //LOG_TRACE("dmg total: ", ftos(unaccounted_damage), " (+", ftos(unaccounted_damage_new), ")");
904 }
905 damage_dealt_time_prev = damage_dealt_time;
906
907 // prevent hitsound when switching spectatee
908 static float spectatee_status_prev = 0;
909 if (spectatee_status != spectatee_status_prev)
911 spectatee_status_prev = spectatee_status;
912}
913
915{
916 // varying sound pitch
917
918 bool have_arc = false;
919 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
920 {
921 entity wepent = viewmodels[slot];
922
923 if(wepent.activeweapon == WEP_ARC)
924 have_arc = true;
925 }
926
927 static float hitsound_time_prev = 0;
928 // HACK: the only way to get the arc to sound consistent with pitch shift is to ignore cl_hitsound_antispam_time
929 bool arc_hack = have_arc && autocvar_cl_hitsound >= 2;
930 if (arc_hack || COMPARE_INCREASING(time, hitsound_time_prev) > autocvar_cl_hitsound_antispam_time)
931 {
933 {
934 float pitch_shift = 1;
936 {
937 // customizable gradient function that crosses (0,a), (c,1) and asymptotically approaches b
941 float d = unaccounted_damage;
942 pitch_shift = (b*d*(a-1) + a*c*(1-b)) / (d*(a-1) + c*(1-b));
943
944 // if pitch shift is reversed, mirror in (max-min)/2 + min
945 if (autocvar_cl_hitsound == 3)
946 {
947 float mirror_value = (a-b)/2 + b;
948 pitch_shift = mirror_value + (mirror_value - pitch_shift);
949 }
950 }
951
952 //LOG_TRACE("dmg total (dmg): ", ftos(unaccounted_damage), " , pitch shift: ", ftos(pitch_shift));
953
954 // todo: avoid very long and very short sounds from wave stretching using different sound files? seems unnecessary
955 // todo: normalize sound pressure levels? seems unnecessary
956
957 sound7(NULL, CH_INFO, SND(HIT), VOL_BASE, ATTN_NONE, pitch_shift * 100, 0);
958 }
960 hitsound_time_prev = time;
961 }
962
963 static float typehit_time_prev = 0;
964 float typehit_time = STAT(TYPEHIT_TIME);
965 if (COMPARE_INCREASING(typehit_time, typehit_time_prev) > autocvar_cl_hitsound_antispam_time)
966 {
967 sound(NULL, CH_INFO, SND_TYPEHIT, VOL_BASE, ATTN_NONE);
968 typehit_time_prev = typehit_time;
969 }
970
971 static float kill_time_prev = 0;
972 float kill_time = STAT(KILL_TIME);
973 if (COMPARE_INCREASING(kill_time, kill_time_prev) > autocvar_cl_hitsound_antispam_time)
974 {
975 sound(NULL, CH_INFO, SND_KILL, VOL_BASE, ATTN_NONE);
976 kill_time_prev = kill_time;
977 }
978}
979
980void HUD_Draw(entity this)
981{
982 // if we don't know gametype and scores yet avoid drawing the scoreboard
983 // also in the very first frames, player state may be inconsistent so avoid drawing the hud at all
984 // e.g. since initial player's health is 0 hud would display the hud_damage effect,
985 // cl_deathscoreboard would show the scoreboard and so on
986 if(!gametype)
987 return;
988
990
991 if(!intermission)
992 {
993 if (MUTATOR_CALLHOOK(HUD_Draw_overlay))
994 {
995 vector col = M_ARGV(0, vector);
996 float alpha_multipl = M_ARGV(1, float);
997 if (alpha_multipl > 0)
999 }
1000 }
1001
1003 if(!intermission)
1004 {
1005 // TODO: mutator hook for these? maybe something more generic!
1006 if(STAT(NADE_TIMER) && autocvar_cl_nade_timer) // give nade top priority, as it's a matter of life and death
1007 {
1008 vector col = '0.25 0.90 1' + vec3(STAT(NADE_TIMER), -STAT(NADE_TIMER), -STAT(NADE_TIMER));
1009 DrawCircleClippedPic(vec2(0.5 * vid_conwidth, 0.6 * vid_conheight), 0.1 * vid_conheight, "gfx/crosshair_ring", STAT(NADE_TIMER), col, autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
1010 drawstring_aspect(eY * 0.64 * vid_conheight, ((autocvar_cl_nade_timer == 2) ? _("Nade timer") : ""), vec2(vid_conwidth, 0.025 * vid_conheight), '1 1 1', 1, DRAWFLAG_NORMAL);
1011 }
1012 else if(STAT(CAPTURE_PROGRESS))
1013 {
1014 DrawCircleClippedPic(vec2(0.5 * vid_conwidth, 0.6 * vid_conheight), 0.1 * vid_conheight, "gfx/crosshair_ring", STAT(CAPTURE_PROGRESS), '0.25 0.90 1', autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
1015 drawstring_aspect(eY * 0.64 * vid_conheight, _("Capture progress"), vec2(vid_conwidth, 0.025 * vid_conheight), '1 1 1', 1, DRAWFLAG_NORMAL);
1016 }
1017 else if(STAT(REVIVE_PROGRESS))
1018 {
1019 DrawCircleClippedPic(vec2(0.5 * vid_conwidth, 0.6 * vid_conheight), 0.1 * vid_conheight, "gfx/crosshair_ring", STAT(REVIVE_PROGRESS), '0.25 0.90 1', autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
1020 drawstring_aspect(eY * 0.64 * vid_conheight, _("Revival progress"), vec2(vid_conwidth, 0.025 * vid_conheight), '1 1 1', 1, DRAWFLAG_NORMAL);
1021 }
1022 }
1024
1025 if(autocvar_r_letterbox == 0)
1026 {
1027 if(autocvar_viewsize < 120)
1028 {
1029 if(!MUTATOR_CALLHOOK(DrawScoreboardAccuracy))
1031
1032 HUD_Main();
1034 }
1035 }
1036
1037 // crosshair goes VERY LAST
1038 UpdateDamage();
1039 HUD_Crosshair(this);
1040 HitSound();
1042}
1043
1045{
1047 return; // don't draw it as spectator!
1048
1052
1053 //float cursor_alpha = 1 - autocvar__menu_alpha;
1054 //cursor_type = CURSOR_NORMAL;
1055 //draw_cursor(viewloc_mousepos, '0.5 0.5 0', "/cursor_move", '1 1 1', cursor_alpha);
1056}
1057
1059{
1060 float cursor_alpha = 1 - autocvar__menu_alpha;
1062 draw_cursor_normal(mousepos, '1 1 1', cursor_alpha);
1063 else if(cursor_type == CURSOR_MOVE)
1064 draw_cursor(mousepos, '0.5 0.5 0', "/cursor_move", '1 1 1', cursor_alpha);
1065 else if(cursor_type == CURSOR_RESIZE)
1066 draw_cursor(mousepos, '0.5 0.5 0', "/cursor_resize", '1 1 1', cursor_alpha);
1067 else if(cursor_type == CURSOR_RESIZE2)
1068 draw_cursor(mousepos, '0.5 0.5 0', "/cursor_resize2", '1 1 1', cursor_alpha);
1069}
1070
1071void HUD_Mouse(entity player)
1072{
1073 if(autocvar__menu_alpha == 1)
1074 return;
1075
1076 if(!cursor_active)
1077 {
1078 if(player.viewloc && (player.viewloc.spawnflags & VIEWLOC_FREEAIM))
1079 ViewLocation_Mouse(); // NOTE: doesn't use cursormode
1080 return;
1081 }
1082
1083 if (cursor_active == -1) // starting to display the cursor
1084 {
1085 // since HUD_Mouse is called by CSQC_UpdateView before CSQC_InputEvent,
1086 // in the first frame mousepos is the mouse position of the last time
1087 // the cursor was displayed, thus we ignore it to avoid a glictch
1088 cursor_active = 1;
1089 return;
1090 }
1091
1094
1098 else
1099 {
1102 if (QuickMenu_IsOpened())
1104 if (HUD_Radar_Clickable())
1106 }
1107
1109
1111}
1112
1114{
1116 return;
1117
1118 // apply night vision effect
1119 vector tc_00, tc_01, tc_10, tc_11;
1120 vector rgb = '0 0 0';
1121 float a;
1122
1124 {
1126 }
1128 {
1130 }
1131
1132 // color tint in yellow
1133 drawfill('0 0 0', autocvar_vid_conwidth * '1 0 0' + autocvar_vid_conheight * '0 1 0', '0.5 1 0.3', 1, DRAWFLAG_MODULATE);
1134
1135 // draw BG
1136 a = Noise_Pink(nightvision_noise, frametime * 1.5) * 0.05 + 0.15;
1137 rgb = '1 1 1';
1138 tc_00 = '0 0 0' + '0.2 0 0' * sin(time * 0.3) + '0 0.3 0' * cos(time * 0.7);
1139 tc_01 = '0 2.25 0' + '0.6 0 0' * cos(time * 1.2) - '0 0.3 0' * sin(time * 2.2);
1140 tc_10 = '1.5 0 0' - '0.2 0 0' * sin(time * 0.5) + '0 0.5 0' * cos(time * 1.7);
1141 //tc_11 = '1 1 0' + '0.6 0 0' * sin(time * 0.6) + '0 0.3 0' * cos(time * 0.1);
1142 tc_11 = tc_01 + tc_10 - tc_00;
1143 R_BeginPolygon("gfx/nightvision-bg", DRAWFLAG_ADDITIVE, true);
1144 R_PolygonVertex('0 0 0', tc_00, rgb, a);
1145 R_PolygonVertex(autocvar_vid_conwidth * '1 0 0', tc_10, rgb, a);
1146 R_PolygonVertex(autocvar_vid_conwidth * '1 0 0' + autocvar_vid_conheight * '0 1 0', tc_11, rgb, a);
1147 R_PolygonVertex(autocvar_vid_conheight * '0 1 0', tc_01, rgb, a);
1148 R_EndPolygon();
1149
1150 // draw FG
1151 a = Noise_Pink(nightvision_noise2, frametime * 0.1) * 0.05 + 0.12;
1152 rgb = '0.3 0.6 0.4' + '0.1 0.4 0.2' * Noise_White(nightvision_noise2, frametime);
1153 tc_00 = '0 0 0' + '1 0 0' * Noise_White(nightvision_noise2, frametime) + '0 1 0' * Noise_White(nightvision_noise2, frametime);
1154 tc_01 = tc_00 + '0 3 0' * (1 + Noise_White(nightvision_noise2, frametime) * 0.2);
1155 tc_10 = tc_00 + '2 0 0' * (1 + Noise_White(nightvision_noise2, frametime) * 0.3);
1156 tc_11 = tc_01 + tc_10 - tc_00;
1157 R_BeginPolygon("gfx/nightvision-fg", DRAWFLAG_ADDITIVE, true);
1158 R_PolygonVertex('0 0 0', tc_00, rgb, a);
1159 R_PolygonVertex(autocvar_vid_conwidth * '1 0 0', tc_10, rgb, a);
1160 R_PolygonVertex(autocvar_vid_conwidth * '1 0 0' + autocvar_vid_conheight * '0 1 0', tc_11, rgb, a);
1161 R_PolygonVertex(autocvar_vid_conheight * '0 1 0', tc_01, rgb, a);
1162 R_EndPolygon();
1163}
1164
1165// visual overlay while in liquids
1166// provides some effects to the postprocessing function
1168{
1170 return;
1171
1172 // improved polyblend
1173 float contentalpha_temp, incontent, liquidalpha, contentfadetime;
1174 vector liquidcolor;
1175
1176 switch(pointcontents(view_origin))
1177 {
1178 case CONTENT_WATER:
1181 incontent = 1;
1182 break;
1183
1184 case CONTENT_LAVA:
1187 incontent = 1;
1188 break;
1189
1190 case CONTENT_SLIME:
1193 incontent = 1;
1194 break;
1195
1196 default:
1197 liquidalpha = 0;
1198 liquidcolor = '0 0 0';
1199 incontent = 0;
1200 break;
1201 }
1202
1203 if(incontent) // fade in/out at different speeds so you can do e.g. instant fade when entering water and slow when leaving it.
1204 { // also lets delcare previous values for blending properties, this way it isn't reset until after you have entered a different content
1205 contentfadetime = autocvar_hud_contents_fadeintime;
1206 liquidalpha_prev = liquidalpha;
1207 liquidcolor_prev = liquidcolor;
1208 }
1209 else
1210 contentfadetime = autocvar_hud_contents_fadeouttime;
1211
1212 contentalpha_temp = bound(0, drawframetime / max(0.0001, contentfadetime), 1);
1213 contentavgalpha = contentavgalpha * (1 - contentalpha_temp) + incontent * contentalpha_temp;
1214
1215 if(contentavgalpha)
1217
1219 {
1221 {
1225 }
1226 else
1227 {
1231 }
1232 }
1233}
1234
1235// visual pain effects on the screen
1236// provides some effects to the postprocessing function
1238{
1239 if(!autocvar_hud_damage || MUTATOR_CALLHOOK(HUD_Damage_show))
1240 return;
1241
1242 vector splash_pos = '0 0 0', splash_size = '0 0 0';
1243 splash_size.x = max(vid_conwidth, vid_conheight);
1244 splash_size.y = max(vid_conwidth, vid_conheight);
1245 splash_pos.x = (vid_conwidth - splash_size.x) / 2;
1246 splash_pos.y = (vid_conheight - splash_size.y) / 2;
1247
1248 float myhealth_flash_temp;
1249 myhealth = STAT(HEALTH);
1250
1251 // fade out
1253 // add new damage
1255
1256 float pain_threshold, pain_threshold_lower, pain_threshold_lower_health;
1257 pain_threshold = autocvar_hud_damage_pain_threshold;
1258 pain_threshold_lower = autocvar_hud_damage_pain_threshold_lower;
1259 pain_threshold_lower_health = autocvar_hud_damage_pain_threshold_lower_health;
1260
1261 if(pain_threshold_lower && myhealth < pain_threshold_lower_health)
1262 {
1263 pain_threshold = pain_threshold - max(autocvar_hud_damage_pain_threshold_pulsating_min, fabs(sin(M_PI * time / autocvar_hud_damage_pain_threshold_pulsating_period))) * pain_threshold_lower * (1 - max(0, myhealth)/pain_threshold_lower_health);
1264 }
1265
1266 myhealth_flash_temp = bound(0, myhealth_flash - pain_threshold, 1);
1267
1268 if(myhealth_prev < 1)
1269 {
1270 if(myhealth >= 1)
1271 {
1272 myhealth_flash = 0; // just spawned, clear the flash immediately
1273 myhealth_flash_temp = 0;
1274 }
1275 else
1276 {
1278 }
1279 }
1280
1281 if(spectatee_status == -1 || intermission)
1282 {
1283 myhealth_flash = 0; // observing, or match ended
1284 myhealth_flash_temp = 0;
1285 }
1286
1288
1289 // IDEA: change damage color/picture based on player model for robot/alien species?
1290 // pro: matches model better
1291 // contra: it's not red because blood is red, but because red is an alarming color, so red should stay
1292 // maybe different reddish pics?
1294 {
1296 {
1297 if(myhealth_flash < pain_threshold) // only randomize when the flash is gone
1299 }
1300 else
1302
1303 if(myhealth_flash_temp > 0)
1305 }
1306 else if(myhealth_flash_temp > 0)
1307 drawpic(splash_pos, "gfx/blood", splash_size, stov(autocvar_hud_damage_color), bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage, DRAWFLAG_NORMAL);
1308
1309 if(autocvar_hud_postprocessing) // we still need to set this anyway even when chase_active is set, this way it doesn't get stuck on.
1310 {
1311 if(autocvar_hud_damage_blur && myhealth_flash_temp)
1312 {
1314 damage_blurpostprocess.y = bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage_blur;
1315 damage_blurpostprocess.z = bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage_blur_alpha;
1316 }
1317 else
1318 {
1322 }
1323 }
1324}
1325
1327{
1329 float e2 = (autocvar_hud_powerup != 0);
1330 bool want_postprocessing = false;
1331 if(autocvar_hud_postprocessing && (e1 || e2)) // TODO: Remove this code and re-do the postprocess handling in the engine, where it properly belongs.
1332 {
1333 // enable or disable rendering types if they are used or not
1334 if(cvar("r_glsl_postprocess_uservec1_enable") != e1) { cvar_set("r_glsl_postprocess_uservec1_enable", ftos(e1)); }
1335 if(cvar("r_glsl_postprocess_uservec2_enable") != e2) { cvar_set("r_glsl_postprocess_uservec2_enable", ftos(e2)); }
1336
1337 // blur postprocess handling done first (used by hud_damage and hud_contents)
1339 {
1342 if(blurradius != old_blurradius || bluralpha != old_bluralpha) // reduce cvar_set spam as much as possible
1343 {
1344 cvar_set("r_glsl_postprocess_uservec1", strcat(ftos(blurradius), " ", ftos(bluralpha), " 0 0"));
1345 old_blurradius = blurradius;
1346 old_bluralpha = bluralpha;
1347 }
1348 want_postprocessing = true;
1349 }
1350 else if(cvar_string("r_glsl_postprocess_uservec1") != "0 0 0 0") // reduce cvar_set spam as much as possible
1351 {
1352 cvar_set("r_glsl_postprocess_uservec1", "0 0 0 0");
1353 old_blurradius = 0;
1354 old_bluralpha = 0;
1355 }
1356
1357 // edge detection postprocess handling done second (used by hud_powerup)
1358 float sharpen_intensity = 0;
1359 FOREACH(StatusEffects, it.instanceOfPowerupStatusEffect,
1360 {
1361 float powerup_finished = StatusEffects_gettime(it, g_statuseffects) - time;
1362 if(powerup_finished > 0)
1363 sharpen_intensity += powerup_finished;
1364 });
1365
1366 sharpen_intensity = bound(0, ((STAT(HEALTH) > 0) ? sharpen_intensity : 0), 5); // Check to see if player is alive (if not, set 0) - also bound to fade out starting at 5 seconds.
1367
1368 if(autocvar_hud_powerup && sharpen_intensity > 0)
1369 {
1370 if(sharpen_intensity != old_sharpen_intensity) // reduce cvar_set spam as much as possible
1371 {
1372 cvar_set("r_glsl_postprocess_uservec2", strcat(ftos((sharpen_intensity / 5) * autocvar_hud_powerup), " ", ftos(-sharpen_intensity * autocvar_hud_powerup), " 0 0"));
1373 old_sharpen_intensity = sharpen_intensity;
1374 }
1375 want_postprocessing = true;
1376 }
1377 else if(cvar_string("r_glsl_postprocess_uservec2") != "0 0 0 0") // reduce cvar_set spam as much as possible
1378 {
1379 cvar_set("r_glsl_postprocess_uservec2", "0 0 0 0");
1381 }
1382 }
1383 if (want_postprocessing)
1384 {
1385 if(cvar("r_glsl_postprocess") == 0)
1386 cvar_set("r_glsl_postprocess", "2");
1387 }
1388 else
1389 {
1390 if(cvar("r_glsl_postprocess") == 2)
1391 cvar_set("r_glsl_postprocess", "0");
1392 }
1393}
1394
1396{
1397 int lock_type = autocvar_cl_lockview;
1398
1401 || intermission > 1
1405 )
1406 )
1407 lock_type = 1;
1408
1409 // lock_type 1: lock origin and angles
1410 // lock_type 2: lock only origin
1411 if(lock_type >= 1)
1412 setproperty(VF_ORIGIN, freeze_org);
1413 else
1414 freeze_org = getpropertyvec(VF_ORIGIN);
1415 if(lock_type == 1)
1416 setproperty(VF_ANGLES, freeze_ang);
1417 else
1418 freeze_ang = getpropertyvec(VF_ANGLES);
1419}
1420
1422{
1423 if(camera_active) // Camera for demo playback
1424 {
1427 else
1428 {
1429 cvar_set("chase_active", ftos(chase_active_backup));
1430 cvar_set("cl_demo_mousegrab", "0");
1431 camera_active = false;
1432 }
1433 }
1434 else
1435 {
1436#ifdef CAMERATEST
1438#else
1440#endif
1441 {
1442 // Enable required Darkplaces cvars
1444 cvar_set("chase_active", "2");
1445 cvar_set("cl_demo_mousegrab", "1");
1446 camera_active = true;
1447 camera_mode = false;
1448 }
1449 }
1450}
1451
1452#ifdef BLURTEST
1453void View_BlurTest()
1454{
1455 if(time > blurtest_time0 && time < blurtest_time1)
1456 {
1457 float t = (time - blurtest_time0) / (blurtest_time1 - blurtest_time0);
1458 float r = t * blurtest_radius;
1459 float f = 1 / (t ** blurtest_power) - 1;
1460
1461 cvar_set("r_glsl_postprocess", "1");
1462 cvar_set("r_glsl_postprocess_uservec1", strcat(ftos(r), " ", ftos(f), " 0 0"));
1463 }
1464 else
1465 {
1466 cvar_set("r_glsl_postprocess", "0");
1467 cvar_set("r_glsl_postprocess_uservec1", "0 0 0 0");
1468 }
1469}
1470#endif
1471
1473{
1474 float is_dead = (STAT(HEALTH) <= 0);
1475
1476 // FIXME do we need this hack?
1477 if(isdemo())
1478 {
1479 // in demos, input_buttons do not work
1481 }
1482 else if(button_zoom
1484 && (spectatee_status >= 0)
1485 && (is_dead || intermission))
1486 {
1487 // no zoom while dead or in intermission please
1488 localcmd("-zoom\n");
1489 button_zoom = false;
1490 }
1491
1492 if(autocvar_fov <= 59.5)
1493 {
1495 {
1496 localcmd("+button9\n");
1498 }
1499 }
1500 else
1501 {
1503 {
1504 localcmd("-button9\n");
1506 }
1507 }
1508
1510 {
1512 {
1513 localcmd("+button12\n");
1514 minigame_wasactive = true;
1515 }
1516 }
1517 else if(minigame_wasactive)
1518 {
1519 localcmd("-button12\n");
1520 minigame_wasactive = false;
1521 }
1522
1523 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
1524 {
1525 entity wepent = viewmodels[slot];
1526
1527 if(wepent.last_switchweapon != wepent.switchweapon)
1528 {
1529 weapontime = time;
1530 wepent.last_switchweapon = wepent.switchweapon;
1532 {
1533 localcmd("-zoom\n");
1534 button_zoom = false;
1535 }
1537 {
1538 localcmd("-fire\n");
1539 localcmd("-fire2\n");
1540 button_attack2 = false;
1541 }
1542 }
1543 if(wepent.last_activeweapon != wepent.activeweapon)
1544 {
1545 wepent.last_activeweapon = wepent.activeweapon;
1546
1547 entity e = wepent.activeweapon;
1548 if(e.netname != "")
1549 localcmd(strcat("\ncl_hook_activeweapon ", e.netname), "\n");
1550 else if(slot == 0)
1551 localcmd("\ncl_hook_activeweapon none\n");
1552 }
1553 }
1554}
1555
1563vector ov_org = '0 0 0';
1564vector ov_mid = '0 0 0';
1567
1569{
1570 ov_org = '0 0 0';
1571 ov_mid = '0 0 0';
1572 ov_worldmin = '0 0 0';
1573 ov_worldmax = '0 0 0';
1575 {
1578
1579 float ov_width = (ov_worldmax.x - ov_worldmin.x);
1580 float ov_height = (ov_worldmax.y - ov_worldmin.y);
1581 float ov_distance = (max(vid_width, vid_height) * max(ov_width, ov_height));
1582
1583 ov_mid = ((ov_worldmax + ov_worldmin) * 0.5);
1584 ov_org = vec3(ov_mid.x, ov_mid.y, (ov_mid.z + ov_distance));
1585
1586 float ov_nearest = vlen(ov_org - vec3(
1590 ));
1591
1592 float ov_furthest = 0;
1593 float dist = 0;
1594
1595 if((dist = vdist((vec3(ov_worldmin.x, ov_worldmin.y, ov_worldmin.z) - ov_org), >, ov_furthest))) { ov_furthest = dist; }
1596 if((dist = vdist((vec3(ov_worldmax.x, ov_worldmin.y, ov_worldmin.z) - ov_org), >, ov_furthest))) { ov_furthest = dist; }
1597 if((dist = vdist((vec3(ov_worldmin.x, ov_worldmax.y, ov_worldmin.z) - ov_org), >, ov_furthest))) { ov_furthest = dist; }
1598 if((dist = vdist((vec3(ov_worldmin.x, ov_worldmin.y, ov_worldmax.z) - ov_org), >, ov_furthest))) { ov_furthest = dist; }
1599 if((dist = vdist((vec3(ov_worldmax.x, ov_worldmax.y, ov_worldmin.z) - ov_org), >, ov_furthest))) { ov_furthest = dist; }
1600 if((dist = vdist((vec3(ov_worldmin.x, ov_worldmax.y, ov_worldmax.z) - ov_org), >, ov_furthest))) { ov_furthest = dist; }
1601 if((dist = vdist((vec3(ov_worldmax.x, ov_worldmin.y, ov_worldmax.z) - ov_org), >, ov_furthest))) { ov_furthest = dist; }
1602 if((dist = vdist((vec3(ov_worldmax.x, ov_worldmax.y, ov_worldmax.z) - ov_org), >, ov_furthest))) { ov_furthest = dist; }
1603
1604 if(!ov_enabled)
1605 {
1606 oldr_nearclip = cvar("r_nearclip");
1607 oldr_farclip_base = cvar("r_farclip_base");
1608 oldr_farclip_world = cvar("r_farclip_world");
1609 oldr_novis = cvar("r_novis");
1610 oldr_useportalculling = cvar("r_useportalculling");
1611 oldr_useinfinitefarclip = cvar("r_useinfinitefarclip");
1612 }
1613
1614 cvar_settemp("r_nearclip", ftos(ov_nearest));
1615 cvar_settemp("r_farclip_base", ftos(ov_furthest));
1616 cvar_settemp("r_farclip_world", "0");
1617 cvar_settemp("r_novis", "1");
1618 cvar_settemp("r_useportalculling", "0");
1619 cvar_settemp("r_useinfinitefarclip", "0");
1620
1621 setproperty(VF_ORIGIN, ov_org);
1622 setproperty(VF_ANGLES, '90 0 0');
1623
1624 ov_enabled = true;
1625
1626 #if 0
1627 LOG_INFOF("OrthoView: org = %s, angles = %s, distance = %f, nearest = %f, furthest = %f",
1628 vtos(ov_org),
1629 vtos(getpropertyvec(VF_ANGLES)),
1630 ov_distance,
1631 ov_nearest,
1632 ov_furthest);
1633 #endif
1634 }
1635 else
1636 {
1637 if(ov_enabled)
1638 {
1639 cvar_set("r_nearclip", ftos(oldr_nearclip));
1640 cvar_set("r_farclip_base", ftos(oldr_farclip_base));
1641 cvar_set("r_farclip_world", ftos(oldr_farclip_world));
1642 cvar_set("r_novis", ftos(oldr_novis));
1643 cvar_set("r_useportalculling", ftos(oldr_useportalculling));
1644 cvar_set("r_useinfinitefarclip", ftos(oldr_useinfinitefarclip));
1645 }
1646 ov_enabled = false;
1647 }
1648}
1649
1651{
1652 vector fov;
1655 else if(csqcplayer.viewloc)
1656 fov = GetViewLocationFOV(110); // enforce 110 fov, so things don't look odd
1657 else
1659
1660 setproperty(VF_FOV, fov);
1661}
1662
1663void CSQC_UpdateView(entity this, float w, float h, bool notmenu)
1664{
1665 TC(int, w); TC(int, h);
1666
1668
1669 ++framecount;
1670
1671 stats_get();
1672 hud = STAT(HUD);
1673
1675
1677
1678 if(autocvar__hud_showbinds_reload) // menu can set this one
1679 {
1681 binddb = db_create();
1682 cvar_set("_hud_showbinds_reload", "0");
1683 }
1684
1685 if(checkextension("DP_CSQC_MINFPS_QUALITY"))
1686 view_quality = getproperty(VF_MINFPS_QUALITY);
1687 else
1688 view_quality = 1;
1689
1692
1693 vector vf_size = getpropertyvec(VF_SIZE);
1694 vector vf_min = getpropertyvec(VF_MIN);
1695 vid_width = vf_size.x;
1696 vid_height = vf_size.y;
1697
1698 ticrate = STAT(MOVEVARS_TICRATE) * STAT(MOVEVARS_TIMESCALE);
1699
1701 {
1702 // in first person view if r_drawviewmodel is off weapon isn't visible
1703 // and server doesn't throw any casing
1704 // switching to 3rd person view r_drawviewmodel is set to -1 to let know the server casings
1705 // can be thrown for self since own weapon model is visible
1706 if (autocvar_r_drawviewmodel == 0 && STAT(HEALTH) > 0)
1707 cvar_set("r_drawviewmodel", "-1");
1708 }
1709 else
1710 {
1712 cvar_set("r_drawviewmodel", "0");
1713 }
1714
1716
1718
1719 if(player_localentnum <= maxclients) // is it a client?
1721 else // then player_localentnum is the vehicle I'm driving
1724
1726 if(!local_player)
1727 local_player = this; // fall back!
1728
1729 if (!View_SpectatorCamera())
1730 View_EventChase(local_player);
1731
1732 // do lockview after event chase camera so that it still applies whenever necessary.
1733 View_Lock();
1734
1736 //WarpZone_FixPMove();
1737
1738 View_Ortho();
1739
1740 // run viewmodel_draw before updating view_angles to the angles calculated by WarpZone_FixView
1741 // viewmodel_draw needs to use the view_angles set by the engine on every CSQC_UpdateView call
1743 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
1744 if(viewmodels[slot].activeweapon)
1746
1747 // Render the Scene
1748 view_origin = getpropertyvec(VF_ORIGIN);
1749 view_angles = getpropertyvec(VF_ANGLES);
1751
1752#ifdef BLURTEST
1753 View_BlurTest();
1754#endif
1755
1757 Fog_Force();
1759
1760 if(drawtime == 0)
1761 drawframetime = 0.01666667; // when we don't know fps yet, we assume 60fps
1762 else
1763 drawframetime = bound(0.000001, time - drawtime, 1);
1764 drawtime = time;
1765
1766 // watch for gametype changes here...
1767 // in ParseStuffCMD the cmd isn't executed yet :/
1768 // might even be better to add the gametype to TE_CSQC_INIT...?
1769 if(!postinit)
1770 PostInit();
1771
1774
1775 if(STAT(GAME_STOPPED) && !game_stopped_time)
1777 else if(game_stopped_time && !STAT(GAME_STOPPED))
1779
1780 // fire intermission hooks and gameend hook here
1781 // gameend hook is executed on CSQC VM shutdown if
1782 // the shutdown happens before intermission start
1783 if (intermission
1784 && (calledhooks & HOOK_START) // ensure that we have initiated a gametype
1785 && !(calledhooks & HOOK_END) // fire only once
1787 {
1788 if(!isdemo())
1789 {
1790 int gamecount = cvar("cl_matchcount");
1791 localcmd("\ncl_hook_gameend\n");
1792 // NOTE: using localcmd here to ensure it's executed AFTER cl_hook_gameend
1793 // earlier versions of the game abuse the hook to set this cvar
1794 localcmd(strcat("cl_matchcount ", itos(gamecount + 1), "\n"));
1795 //cvar_set("cl_matchcount", itos(gamecount + 1));
1797
1798 localcmd("\ncl_hook_gameintermission\n");
1800 }
1801 else
1802 {
1803 localcmd("\ncl_hook_demointermission\n");
1805 }
1806 }
1807
1809
1810 Announcer();
1811
1813
1815
1816 // ALWAYS Clear Current Scene First
1817 clearscene();
1818
1819 setproperty(VF_ORIGIN, view_origin);
1820 setproperty(VF_ANGLES, view_angles);
1821
1822 // FIXME engine bug? VF_SIZE and VF_MIN are not restored to sensible values by this
1823 setproperty(VF_SIZE, vf_size);
1824 setproperty(VF_MIN, vf_min);
1825
1826 // Assign Standard Viewflags
1827 // Draw the World (and sky)
1828 setproperty(VF_DRAWWORLD, 1);
1829
1833
1835
1837
1838 setproperty(VF_DRAWCROSSHAIR, 0); // hide engine crosshair
1839 setproperty(VF_DRAWENGINESBAR, 0); // hide engine status bar
1840
1841 IL_EACH(g_drawables, it.draw, it.draw(it));
1842
1843 addentities(MASK_NORMAL | MASK_ENGINE | MASK_ENGINEVIEWMODELS); // TODO: .health is used in cl_deathfade (a feature we have turned off currently)
1844 renderscene();
1845
1846 // Now the the scene has been rendered, begin with the 2D drawing functions
1847
1849 DrawReticle(local_player);
1850 HUD_Contents();
1851 HUD_Damage();
1853
1856
1857 // draw 2D entities
1858 IL_EACH(g_drawables_2d, it.draw2d, it.draw2d(it));
1859 IL_EACH(g_damagetext, it.draw2d, it.draw2d(it));
1861#if ENABLE_DEBUGDRAW
1862 Debug_Draw();
1863#endif
1864
1866 {
1868 cvar_set("_scoreboard_team_selection", "0");
1869 }
1871
1872 HUD_Draw(this); // this parameter for deep vehicle function
1873
1875 {
1876 localcmd("\n", NextFrameCommand, "\n");
1878 }
1879
1880 HUD_Mouse(local_player);
1881
1882 cl_notice_run();
1884 Net_Flush();
1885
1886 // let's reset the view back to normal for the end
1887 setproperty(VF_MIN, '0 0 0');
1888 setproperty(VF_SIZE, '1 0 0' * w + '0 1 0' * h);
1889
1890 IL_ENDFRAME();
1891}
1892
1893
1894// following vectors must be global to allow seamless switching between camera modes
1897{
1898 float speed, attenuation, dimensions;
1899 vector tmp;
1900
1902 {
1903 camera_offset = '0 0 0';
1904 current_angles = '0 0 0';
1905 camera_direction = '0 0 0';
1906 camera_offset.z += 30;
1907 camera_offset.x += 30 * -cos(current_angles.y * DEG2RAD);
1908 camera_offset.y += 30 * -sin(current_angles.y * DEG2RAD);
1911 cvar_set("camera_reset", "0");
1913 }
1914
1915 // Camera angles
1916 if( camera_roll )
1918
1920 {
1921 vector dir;
1922 float n;
1923
1925 n = mouse_angles.z;
1927 mouse_angles.x = mouse_angles.x * -1;
1928 mouse_angles.z = n;
1929 }
1930 else
1931 {
1932 tmp = getmousepos() * 0.1;
1934 {
1935 mouse_angles.x += tmp.y * cos(mouse_angles.z * DEG2RAD) + (tmp.x * sin(mouse_angles.z * DEG2RAD));
1936 mouse_angles.y -= tmp.x * cos(mouse_angles.z * DEG2RAD) + (tmp.y * -sin(mouse_angles.z * DEG2RAD));
1937 }
1938 }
1939
1942 else
1944
1945 attenuation = 1 / max(1, attenuation);
1946 current_angles += (mouse_angles - current_angles) * attenuation;
1947
1948 // limit current pitch angle to sane values
1949 if (current_angles.x < -90) current_angles.x = -90;
1950 if (current_angles.x > 90 ) current_angles.x = 90;
1951
1952 // limit mouse and current yaw angles to standard values simultaneously so that the difference
1953 // between these angles is not altered
1954 while (current_angles.y < -180 && mouse_angles.y < -180) {current_angles.y += 360; mouse_angles.y += 360;}
1955 while (current_angles.y > 180 && mouse_angles.y > 180 ) {current_angles.y -= 360; mouse_angles.y -= 360;}
1956
1957 // Camera position
1958 tmp = '0 0 0';
1959 dimensions = 0;
1960
1961 if( camera_direction.x )
1962 {
1963 tmp.x = camera_direction.x * cos(current_angles.y * DEG2RAD);
1964 tmp.y = camera_direction.x * sin(current_angles.y * DEG2RAD);
1966 tmp.z = camera_direction.x * -sin(current_angles.x * DEG2RAD);
1967 ++dimensions;
1968 }
1969
1970 if( camera_direction.y )
1971 {
1972 tmp.x += camera_direction.y * -sin(current_angles.y * DEG2RAD);
1974 tmp.z += camera_direction.y * sin(current_angles.z * DEG2RAD);
1975 ++dimensions;
1976 }
1977
1978 if( camera_direction.z )
1979 {
1980 tmp.z += camera_direction.z * cos(current_angles.z * DEG2RAD);
1981 ++dimensions;
1982 }
1983
1986 else
1988
1989 if(dimensions)
1990 {
1991 speed = speed * sqrt(1 / dimensions);
1992 camera_offset += tmp * speed;
1993 }
1994
1996
1997 // Camera modes
1999 {
2000 if ( camera_mode == CAMERA_CHASE )
2001 {
2004 }
2005
2008 }
2009 else
2010 {
2011 if ( camera_mode == CAMERA_FREE )
2012 {
2016 }
2017
2019
2021 current_origin += (view_origin - current_origin) * attenuation;
2022 else
2024
2026 }
2027
2028 setproperty(VF_ANGLES, current_angles);
2029 setproperty(VF_ORIGIN, current_position);
2030}
void anim_update(entity e)
Update e.frame based on its animstate relative to time.
Definition anim.qc:36
void anim_set(entity e, vector anim, bool looping, bool override, bool restart)
Definition anim.qc:6
float animstate_endtime
Definition anim.qh:38
bool animstate_override
true for one cycle, then changed to false
Definition anim.qh:42
bool animstate_looping
whether to repeat
Definition anim.qh:40
const int ANIMIMPLICITSTATE_INAIR
void Announcer()
Definition announcer.qc:228
#define MUTATOR_CALLHOOK(id,...)
Definition base.qh:143
float height
Definition bobbing.qc:3
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
entity active_minigame
void HUD_Minigame_Mouse()
bool HUD_MinigameMenu_IsOpened()
void CSQCPlayer_SetCamera()
Called once per CSQC_UpdateView()
Definition cl_player.qc:573
entity csqcplayer
Definition cl_player.qh:26
float height
vehicle 3rd person view distance
Definition vehicle.qh:42
vector view_ofs
vehicle 3rd person view offset
Definition vehicle.qh:40
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
Definition weapon.qh:44
string mdl
M: modelname : name of model (without g_ v_ or h_ prefixes)
Definition weapon.qh:61
virtual void wr_zoomdir()
(CLIENT) check whether the weapon should zoom (special handling)
Definition weapon.qh:121
virtual void wr_viewmodel()
(CLIENT) weapon specific view model
Definition weapon.qh:123
void drawstring_aspect(vector pos, string text, vector sz, vector color, float theAlpha, float drawflag)
Definition draw.qc:110
void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector rgb, float a, float drawflag)
Definition draw.qc:190
#define drawpic(position, pic, size, rgb, alpha, flag)
Definition draw.qh:21
#define drawfill(position, size, rgb, alpha, flag)
Definition draw.qh:36
void Fog_Force()
Definition main.qc:1037
void Welcome_Message_Show_Try()
Definition main.qc:1462
void PostInit()
Definition main.qc:463
void ignore_list_apply()
Definition main.qc:672
vector camera_direction
Definition main.qh:156
float spectatee_status_changed_time
Definition main.qh:198
float zoomin_effect
Definition main.qh:119
float current_viewzoom
Definition main.qh:118
bool autocvar_cl_unpress_zoom_on_death
Definition main.qh:8
int calledhooks
Definition main.qh:164
IntrusiveList g_drawables
Definition main.qh:91
int vid_width
Definition main.qh:150
vector view_origin
Definition main.qh:109
bool autocvar_cl_unpress_zoom_on_weapon_switch
Definition main.qh:9
int framecount
Definition main.qh:180
bool autocvar_cl_unpress_attack_on_weapon_switch
Definition main.qh:10
bool postinit
Definition main.qh:42
int binddb
Definition main.qh:191
float chase_active_backup
Definition main.qh:154
float view_quality
Definition main.qh:174
IntrusiveList g_damagetext
Definition main.qh:93
bool button_zoom
Definition main.qh:113
const int HOOK_START
Definition main.qh:165
bool button_attack2
Definition main.qh:116
int spectatee_status
the -1 disables HUD panels before CSQC receives necessary data
Definition main.qh:197
entity gametype
Definition main.qh:43
float drawframetime
Definition main.qh:108
int serverflags
Definition main.qh:211
vector view_up
Definition main.qh:109
const int HOOK_INTERMISSION
Definition main.qh:167
float vid_pixelheight
Definition main.qh:151
int hud
Definition main.qh:173
const int HOOK_END
Definition main.qh:166
bool autocvar__hud_showbinds_reload
Definition main.qh:13
vector view_right
Definition main.qh:109
float camera_active
Definition main.qh:153
float ticrate
Definition main.qh:209
int vid_height
Definition main.qh:150
vector view_forward
Definition main.qh:109
bool spectatorbutton_zoom
Definition main.qh:114
bool ignore_list_apply_time
Definition main.qh:131
float current_zoomfraction
Definition main.qh:148
IntrusiveList g_drawables_2d
Definition main.qh:92
float camera_roll
Definition main.qh:155
#define M_ARGV(x, type)
Definition events.qh:17
void unpause_update()
Definition player.qh:357
#define PHYS_INPUT_BUTTON_ZOOM(s)
Definition player.qh:153
#define PHYS_INPUT_BUTTON_ATCK2(s)
Definition player.qh:152
void execute_next_frame()
Definition util.qc:1748
float cvar_settemp(string tmp_cvar, string tmp_value)
Definition util.qc:811
vector mi_picmin
Definition util.qh:131
bool autocvar_cl_gentle
Definition util.qh:236
#define COMPARE_INCREASING(to, from)
Definition util.qh:268
vector mi_picmax
Definition util.qh:132
const int HUD_BUMBLEBEE_GUN
Definition constants.qh:48
const int SERVERFLAG_ALLOW_FULLBRIGHT
Definition constants.qh:16
const int HUD_NORMAL
Definition constants.qh:47
#define EFMASK_CHEAP
Definition constants.qh:107
void DrawReticle(entity this)
Definition crosshair.qc:649
void HUD_Crosshair(entity this)
Definition crosshair.qc:213
const float MASK_ENGINE
const float VF_DRAWENGINESBAR
const float DRAWFLAG_NORMAL
float maxclients
vector pmove_vel
const float ATTN_NONE
float DEG2RAD
const float VF_MIN
const float VF_ORIGIN
const float DRAWFLAG_ADDITIVE
float frametime
const float MASK_NORMAL
const float VF_DRAWWORLD
float player_localnum
vector pmove_org
vector velocity
vector view_angles
const float CONTENT_WATER
const float EF_FULLBRIGHT
const float VF_MINFPS_QUALITY
float time
vector trace_endpos
float trace_startsolid
const float VF_FOV
float MOVE_WORLDONLY
const float VF_ANGLES
const float DRAWFLAG_MODULATE
float player_localentnum
float intermission
const float EF_NODEPTHTEST
vector origin
const float VF_DRAWCROSSHAIR
float trace_fraction
const float CONTENT_LAVA
const float VF_SIZE
float GETTIME_FRAMESTART
const float MASK_ENGINEVIEWMODELS
const float CONTENT_SLIME
void CSQCModel_Effects_Apply(entity this)
float m_alpha
int state
#define MAKE_VECTORS(angles, forward, right, up)
Same as the makevectors builtin but uses the provided locals instead of the v_* globals.
float speed
Definition dynlight.qc:9
ent angles
Definition ent_cs.qc:121
int entcs_GetTeam(int i)
Definition ent_cs.qh:133
entity CSQCModel_server2csqc(int i)
Definition cl_model.qc:314
int entcs_GetClientColors(int i)
Definition ent_cs.qh:115
void draw_cursor_normal(vector pos, vector col, float a)
Definition hud.qc:37
void draw_cursor(vector pos, vector ofs, string img, vector col, float a)
Definition hud.qc:31
void HUD_Main()
Definition hud.qc:682
void HUD_Scale_Enable()
Definition hud.qc:91
void Hud_Dynamic_Frame()
Definition hud.qc:589
void HUD_Scale_Disable()
Definition hud.qc:84
float autocvar__menu_alpha
Definition hud.qh:187
void HUD_Radar_Mouse()
Definition radar.qc:123
bool QuickMenu_IsOpened()
Definition quickmenu.qc:291
bool autocvar_hud_cursormode
Definition hud.qh:191
float current_player
Definition hud.qh:185
vector cl_followmodel_ofs
Definition hud.qh:218
float weapontime
Definition hud.qh:122
vector mousepos
Definition hud.qh:103
float cl_followmodel_time
Definition hud.qh:219
bool HUD_Radar_Clickable()
Definition radar.qc:26
void HUD_Panel_Mouse()
bool autocvar__hud_configure
Definition hud_config.qh:3
int prevMouseClicked
Definition hud_config.qh:14
int mouseClicked
Definition hud_config.qh:13
void Impulse_Send(entity imp)
Definition all.qh:17
#define itos(i)
Definition int.qh:6
ERASEABLE void IL_ENDFRAME()
#define IL_EACH(this, cond, body)
#define FOREACH(list, cond, body)
Definition iter.qh:19
float K_MWHEELDOWN
Definition keycodes.qc:133
float K_MWHEELUP
Definition keycodes.qc:132
#define CSQC_UpdateView
Definition _all.inc:298
#define TC(T, sym)
Definition _all.inc:82
noref float vid_conwidth
Definition draw.qh:8
noref float vid_conheight
Definition draw.qh:9
void Net_Flush()
Definition net.qh:212
const int MSG_C2S
Definition net.qh:199
#define WriteHeader(to, id)
Definition net.qh:221
const int REPLICATEVARS_CHECK
Definition replicate.qh:5
#define STAT(...)
Definition stats.qh:82
void stats_get()
Get all stats and store them as globals, access with STAT(ID)
Definition stats.qh:81
void WarpZone_FixView()
Definition client.qc:225
void WarpZone_TraceLine(vector org, vector end, float nomonsters, entity forent)
Definition common.qc:348
vector WarpZone_TransformVAngles(entity wz, vector ang)
Definition common.qc:524
void WarpZone_TraceBox(vector org, vector mi, vector ma, vector end, float nomonsters, entity forent)
Definition common.qc:343
entity WarpZone_trace_transform
Definition common.qh:37
#define LOG_INFOF(...)
Definition log.qh:66
ERASEABLE void db_close(int db)
Definition map.qh:84
ERASEABLE int db_create()
Definition map.qh:25
const int VIEWLOC_FREEAIM
Definition viewloc.qh:5
entity viewloc
Definition viewloc.qh:13
ERASEABLE float float2range11(float f)
continuous function mapping all reals into -1..1
Definition math.qh:200
ERASEABLE float almost_equals(float a, float b)
Definition math.qh:219
ERASEABLE float map_bound_ranges(float value, float src_min, float src_max, float dest_min, float dest_max)
Same as map_ranges except that values outside the source range are clamped to min or max.
Definition math.qh:372
float exp(float e)
Definition mathlib.qc:73
#define M_PI
Definition mathlib.qh:108
string name
Definition menu.qh:30
void localcmd(string command,...)
void cvar_set(string name, string value)
float isdemo()
float bound(float min, float value, float max)
float cvar(string name)
float gettime(void)
float cos(float f)
vector stov(string s)
const string cvar_string(string name)
float vlen(vector v)
void WriteShort(float data, float dest, float desto)
vector vectoangles(vector v)
float sqrt(float f)
vector randomvec(void)
float sin(float f)
string vtos(vector v)
float min(float f,...)
float checkextension(string ext)
float rint(float f)
vector normalize(vector v)
string ftos(float f)
float fabs(float f)
float floor(float f)
vector getmousepos(void)
float max(float f,...)
void TargetMusic_Advance()
void cl_notice_run()
Definition net_notice.qc:55
string string_null
Definition nil.qh:9
ERASEABLE float Noise_Pink(entity e, float dt)
Definition noise.qh:18
ERASEABLE float Noise_White(entity e, float dt)
Definition noise.qh:29
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
void Local_Notification_Queue_Process()
Definition all.qc:1218
void ReplicateVars(bool would_destroy)
Definition all.qh:895
#define NULL
Definition post.qh:14
void QuickMenu_Mouse()
Definition quickmenu.qc:546
#define REGISTRY_GET(id, i)
Definition registry.qh:43
bool Scoreboard_WouldDraw()
void Scoreboard_UI_Enable(int mode)
bool scoreboard_active
Definition scoreboard.qh:16
bool autocvar__scoreboard_team_selection
Definition scoreboard.qh:41
vector
Definition self.qh:92
int dir
Definition impulse.qc:89
void Draw_ShowNames_All()
Definition shownames.qc:223
const float VOL_BASE
Definition sound.qh:36
const int CH_INFO
Definition sound.qh:6
#define sound(e, c, s, v, a)
Definition sound.qh:52
#define SND(id)
Definition all.qh:35
#define STATIC_INIT(func)
during worldspawn
Definition static.qh:32
bool StatusEffects_active(StatusEffect this, entity actor)
int ColorTranslateMode
Definition string.qh:193
int myteam
Definition teams.qh:60
const vector eY
Definition vector.qh:45
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
Definition vector.qh:8
#define ROLL(v)
Definition vector.qh:83
#define PITCH(v)
Definition vector.qh:81
#define YAW(v)
Definition vector.qh:82
#define vec2(...)
Definition vector.qh:90
#define vec3(_x, _y, _z)
Definition vector.qh:95
vector ov_worldmax
Definition view.qc:1566
void HUD_Draw(entity this)
Definition view.qc:980
vector current_position
Definition view.qc:1895
bool autocvar_cl_followmodel_velocity_absolute
Definition view.qc:57
float oldr_farclip_world
Definition view.qc:1559
void update_mousepos()
Definition view.qc:388
float autocvar_cl_leanmodel_lowpass
Definition view.qc:64
float liquidalpha_prev
Definition view.qc:652
bool minigame_wasactive
Definition view.qc:634
float weapon_nextthink
Definition view.qc:288
#define highpass2_limited(value, frac, limit, ref_store, ref_out)
Definition view.qc:96
vector current_camera_offset
Definition view.qc:1895
float autocvar_cl_followmodel_limit
Definition view.qc:53
void UpdateDamage()
Definition view.qc:890
float autocvar_cl_viewmodel_alpha_min
Definition view.qc:44
int showfps_framecounter
Definition view.qc:396
vector ov_mid
Definition view.qc:1564
float contentavgalpha
Definition view.qc:652
const float MAX_ZOOMFACTOR
Definition view.qc:447
void View_Ortho()
Definition view.qc:1568
float oldr_novis
Definition view.qc:1560
vector mouse_angles
Definition view.qc:1895
void ViewLocation_Mouse()
Definition view.qc:1044
void HitSound()
Definition view.qc:914
bool View_SpectatorCamera()
Definition view.qc:655
void fpscounter_update()
Definition view.qc:398
#define highpass2(value, frac, ref_store, ref_out)
Definition view.qc:91
void View_Lock()
Definition view.qc:1395
vector GetOrthoviewFOV(vector ov_worldmin, vector ov_worldmax, vector ov_mid, vector ov_org)
Definition view.qc:621
float weapon_switchdelay
Definition view.qc:290
float autocvar_cl_leanmodel
Definition view.qc:59
void calc_followmodel_ofs(entity view)
Definition view.qc:113
float weapon_eta_last
Definition view.qc:289
entity nightvision_noise2
Definition view.qc:642
const float CAMERA_CHASE
Definition view.qc:638
float autocvar_cl_followmodel_velocity_lowpass
Definition view.qc:54
vector project_3d_to_2d(vector vec)
Definition view.qc:373
void ZoomScroll(float nPrimary)
Definition view.qc:450
float myhealth_flash
Definition view.qc:645
float old_blurradius
Definition view.qc:647
string name_last
Definition view.qc:292
vector freeze_ang
Definition view.qc:641
float myhealth_prev
Definition view.qc:644
float autocvar_cl_followmodel
Definition view.qc:51
float zoomscroll_factor_target
Definition view.qc:449
float autocvar_cl_bobmodel_speed
Definition view.qc:47
float autocvar_cl_followmodel_speed
Definition view.qc:52
vector current_origin
Definition view.qc:1895
entity nightvision_noise
Definition view.qc:642
vector ov_worldmin
Definition view.qc:1565
float old_bluralpha
Definition view.qc:647
#define lowpass3(value, frac, ref_store, ref_out)
Definition view.qc:101
vector liquidcolor_prev
Definition view.qc:653
void View_DemoCamera()
Definition view.qc:1421
float camera_mode
Definition view.qc:636
vector damage_blurpostprocess
Definition view.qc:888
#define lowpass2(value, frac, ref_store, ref_out)
Definition view.qc:86
vector freeze_org
Definition view.qc:641
float oldr_farclip_base
Definition view.qc:1558
void View_UpdateFov()
Definition view.qc:1650
void View_PostProcessing()
Definition view.qc:1326
vector bobmodel_ofs(entity view)
Definition view.qc:203
bool View_InputEvent(int bInputType, float nPrimary, float nSecondary)
Definition view.qc:465
void HUD_Damage()
Definition view.qc:1237
bool ov_enabled
Definition view.qc:1556
float autocvar_cl_followmodel_highpass
Definition view.qc:55
float autocvar_cl_viewmodel_alpha
Definition view.qc:43
float autocvar_cl_followmodel_lowpass
Definition view.qc:56
float myhealth
Definition view.qc:644
float eventchase_running
Definition view.qc:729
string NextFrameCommand
Definition view.qc:639
vector GetViewLocationFOV(float fov)
Definition view.qc:612
float oldr_useinfinitefarclip
Definition view.qc:1562
float autocvar_cl_leanmodel_highpass1
Definition view.qc:62
void View_CheckButtonStatus()
Definition view.qc:1472
vector current_angles
Definition view.qc:1895
vector camera_offset
Definition view.qc:1895
float oldr_nearclip
Definition view.qc:1557
float autocvar_cl_bobmodel_side
Definition view.qc:48
void HUD_Contents()
Definition view.qc:1167
float avgspeed
Definition view.qc:487
float oldr_useportalculling
Definition view.qc:1561
void CSQC_Demo_Camera()
Definition view.qc:1896
void viewmodel_draw(entity this)
Definition view.qc:294
vector leanmodel_ofs(entity view)
Definition view.qc:167
void HUD_Mouse(entity player)
Definition view.qc:1071
int WantEventchase(entity this, bool want_vehiclechase)
Definition view.qc:730
vector GetCurrentFov(float fov)
Definition view.qc:488
#define avg_factor(avg_time)
Definition view.qc:66
void View_NightVision()
Definition view.qc:1113
bool projected_on_screen(vector screen_pos)
Definition view.qc:379
void View_EventChase(entity this)
Definition view.qc:767
float autocvar_cl_leanmodel_limit
Definition view.qc:61
float autocvar_cl_leanmodel_speed
Definition view.qc:60
float showfps_prevfps_time
Definition view.qc:395
float zoomscroll_factor
Definition view.qc:448
float autocvar_cl_bobmodel_up
Definition view.qc:49
bool autocvar_cl_bobmodel
Definition view.qc:46
void viewmodel_animate(entity this)
Definition view.qc:258
vector myhealth_gentlergb
Definition view.qc:650
const float CAMERA_FREE
Definition view.qc:637
#define highpass3(value, frac, ref_store, ref_out)
Definition view.qc:107
vector content_blurpostprocess
Definition view.qc:888
bool IsZooming(bool ignore_spectatorbutton_zoom)
Definition view.qc:424
float autocvar_cl_leanmodel_highpass
Definition view.qc:63
float eventchase_current_distance
Definition view.qc:728
float old_sharpen_intensity
Definition view.qc:648
vector ov_org
Definition view.qc:1563
void HUD_Cursor_Show()
Definition view.qc:1058
float autocvar_cl_hitsound_max_pitch
Definition view.qh:83
float autocvar_cl_eventchase_speed
Definition view.qh:91
float autocvar_cl_velocityzoom_time
Definition view.qh:31
bool autocvar_cl_orthoview
Definition view.qh:21
const int CURSOR_RESIZE
Definition view.qh:116
float autocvar_hud_damage_pain_threshold_pulsating_period
Definition view.qh:64
float autocvar_hud_damage_pain_threshold_lower_health
Definition view.qh:62
float autocvar_camera_mouse_threshold
Definition view.qh:11
vector autocvar_cl_eventchase_vehicle_viewoffset
Definition view.qh:79
float autocvar_camera_speed_free
Definition view.qh:15
float autocvar_cl_velocityzoom_speed
Definition view.qh:30
string autocvar__togglezoom
Definition view.qh:95
int autocvar_chase_active
Definition view.qh:17
string autocvar_hud_contents_slime_color
Definition view.qh:48
float autocvar_camera_look_attenuation
Definition view.qh:9
float unaccounted_damage
Definition view.qh:120
float autocvar_cl_hitsound_min_pitch
Definition view.qh:82
float autocvar_cl_eventchase_vehicle_distance
Definition view.qh:80
bool autocvar_hud_contents
Definition view.qh:40
bool autocvar_cl_eventchase_vehicle
Definition view.qh:78
int autocvar_cl_gentle_damage
Definition view.qh:19
vector viewloc_mousepos
Definition view.qh:110
bool autocvar_hud_powerup
Definition view.qh:65
int cursor_active
Definition view.qh:112
vector autocvar_cl_gunoffset
Definition view.qh:98
float autocvar_hud_damage_fade_rate
Definition view.qh:56
int autocvar_cl_nade_timer
Definition view.qh:96
bool autocvar_camera_enable
Definition view.qh:6
vector autocvar_cl_eventchase_viewoffset
Definition view.qh:94
const int CURSOR_MOVE
Definition view.qh:115
bool autocvar_camera_chase_smoothly
Definition view.qh:5
float autocvar_hud_colorflash_alpha
Definition view.qh:39
float zoomscript_caught
Definition view.qh:121
float dmg_take
Definition view.qh:123
float autocvar_hud_damage_pain_threshold
Definition view.qh:60
bool autocvar_r_drawviewmodel
Definition view.qh:97
float autocvar_cl_velocityzoom_factor
Definition view.qh:28
string autocvar_hud_contents_lava_color
Definition view.qh:46
float autocvar_hud_contents_water_alpha
Definition view.qh:49
float autocvar_cl_spawnzoom_speed
Definition view.qh:24
vector autocvar_cl_eventchase_mins
Definition view.qh:93
bool autocvar_r_fullbright
Definition view.qh:71
float autocvar_cl_spawnzoom_factor
Definition view.qh:25
float autocvar_hud_damage_gentle_alpha_multiplier
Definition view.qh:57
float autocvar_hud_contents_blur_alpha
Definition view.qh:42
bool autocvar_camera_forward_follows
Definition view.qh:7
float autocvar_hud_contents_fadeouttime
Definition view.qh:44
string autocvar_hud_damage_gentle_color
Definition view.qh:58
float autocvar_viewsize
Definition view.qh:77
bool autocvar_cl_eventchase_frozen
Definition view.qh:90
float autocvar_hud_contents_fadeintime
Definition view.qh:43
float autocvar_cl_eventchase_distance
Definition view.qh:89
float autocvar_camera_speed_chase
Definition view.qh:14
float autocvar_hud_contents_lava_alpha
Definition view.qh:45
float autocvar_vid_pixelheight
Definition view.qh:76
float autocvar_cl_hitsound_antispam_time
Definition view.qh:85
float autocvar_cl_zoomsensitivity
Definition view.qh:33
float autocvar_cl_hitsound_nom_damage
Definition view.qh:84
float autocvar_cl_zoomscroll_speed
Definition view.qh:37
float autocvar_menu_mouse_speed
Definition view.qh:69
float autocvar_hud_postprocessing_maxbluralpha
Definition view.qh:67
int autocvar_vid_conwidth
Definition view.qh:75
float autocvar_hud_damage_blur_alpha
Definition view.qh:53
int cursor_type
Definition view.qh:113
bool autocvar_camera_free
Definition view.qh:8
string autocvar_hud_damage_color
Definition view.qh:54
int autocvar_cl_eventchase_death
Definition view.qh:88
bool autocvar_cl_zoomscroll
Definition view.qh:35
float autocvar_camera_look_player
Definition view.qh:10
int autocvar_vid_conheight
Definition view.qh:74
float autocvar_hud_contents_blur
Definition view.qh:41
float autocvar_hud_postprocessing_maxblurradius
Definition view.qh:68
bool autocvar_hud_postprocessing
Definition view.qh:66
bool autocvar_cl_eventchase_spectated_change
Definition view.qh:86
float autocvar_cl_eventchase_spectated_change_time
Definition view.qh:87
bool autocvar_hud_damage
Definition view.qh:51
float autocvar_camera_speed_roll
Definition view.qh:16
bool autocvar_camera_reset
Definition view.qh:12
int autocvar_cl_velocityzoom_type
Definition view.qh:29
float autocvar_hud_damage_blur
Definition view.qh:52
bool autocvar_cl_velocityzoom_enabled
Definition view.qh:27
float autocvar_hud_damage_pain_threshold_lower
Definition view.qh:61
float autocvar_cl_zoomfactor
Definition view.qh:32
bool autocvar_cl_stripcolorcodes
Definition view.qh:26
float autocvar_cl_zoomspeed
Definition view.qh:34
int autocvar_cl_hitsound
Definition view.qh:81
float autocvar_cl_zoomscroll_scale
Definition view.qh:36
float autocvar_camera_speed_attenuation
Definition view.qh:13
vector autocvar_cl_eventchase_maxs
Definition view.qh:92
bool autocvar_cl_lockview
Definition view.qh:20
float autocvar_fov
Definition view.qh:38
float drawtime
Definition view.qh:119
bool autocvar_cl_spawnzoom
Definition view.qh:23
float intermission_time
Definition view.qh:131
float autocvar_hud_damage_maxalpha
Definition view.qh:59
entity viewmodels[MAX_WEAPONSLOTS]
Definition view.qh:108
float autocvar_r_letterbox
Definition view.qh:72
float autocvar_hud_contents_slime_alpha
Definition view.qh:47
int autocvar_r_fakelight
Definition view.qh:70
float game_stopped_time
Definition view.qh:132
string autocvar_hud_contents_water_color
Definition view.qh:50
const int CURSOR_RESIZE2
Definition view.qh:117
float autocvar_hud_damage_pain_threshold_pulsating_min
Definition view.qh:63
float autocvar_hud_damage_factor
Definition view.qh:55
const int CURSOR_NORMAL
Definition view.qh:114
void WaypointSprite_Load()
void CL_WeaponEntity_SetModel(entity this, string name, bool _anim)
supported formats:
Definition all.qc:347
vector anim_idle
Definition all.qh:399
vector weaponentity_glowmod(Weapon wep, int c, entity wepent)
Definition all.qh:378
const int MAX_WEAPONSLOTS
Definition weapon.qh:16
const int WS_CLEAR
no weapon selected
Definition weapon.qh:33
const int WS_RAISE
raise frame
Definition weapon.qh:35
const int WS_DROP
deselecting frame
Definition weapon.qh:37
void Accuracy_LoadLevels()
Definition weapons.qc:38
int m_skin
Definition wepent.qh:40
Weapon activeweapon
Definition wepent.qh:34