]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/client/View.qc
Merge branch 'master' into mirceakitsune/hud_postprocessing
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / View.qc
index 059fd0f4e48fb3a2391da2e016f8e07e53b0655b..ae42a7b18c41dbce9a4a96d4c42faec6fa96f715 100644 (file)
@@ -361,11 +361,20 @@ float use_nex_chargepool;
 float myhealth, myhealth_prev;
 float myhealth_flash;
 
+float old_blurradius, old_bluralpha;
+float old_sharpen_intensity;
+
 vector myhealth_gentlergb;
 
 float contentavgalpha, liquidalpha_prev;
 vector liquidcolor_prev;
 
+float eventchase_current_distance;
+
+vector damage_blurpostprocess, content_blurpostprocess;
+
+float checkfail[16];
+
 void CSQC_UpdateView(float w, float h)
 {
        entity e;
@@ -375,6 +384,17 @@ void CSQC_UpdateView(float w, float h)
        vector vf_size, vf_min;
        float a;
 
+       button_attack2 = (input_buttons & BUTTON_3);
+       button_zoom = (input_buttons & BUTTON_4);
+
+#define CHECKFAIL_ASSERT(flag,func,parm,val) { float checkfailv; checkfailv = (func)(parm); if(checkfailv != (val)) { if(!checkfail[(flag)]) localcmd(sprintf("\ncmd checkfail %s %s %d %d\n", #func, parm, val, checkfailv)); checkfail[(flag)] = 1; } } ENDS_WITH_CURLY_BRACE
+       CHECKFAIL_ASSERT(0, cvar_type, "\{100}\{105}\{118}\{48}\{95}\{101}\{118}\{97}\{100}\{101}", 0);
+       CHECKFAIL_ASSERT(1, cvar_type, "\{97}\{97}\{95}\{101}\{110}\{97}\{98}\{108}\{101}", 0);
+       CHECKFAIL_ASSERT(2, cvar, "\{114}\{95}\{115}\{104}\{111}\{119}\{100}\{105}\{115}\{97}\{98}\{108}\{101}\{100}\{101}\{112}\{116}\{104}\{116}\{101}\{115}\{116}", 0);
+       CHECKFAIL_ASSERT(3, cvar, "\{114}\{95}\{115}\{104}\{111}\{119}\{111}\{118}\{101}\{114}\{100}\{114}\{97}\{119}", 0);
+       CHECKFAIL_ASSERT(4, cvar, "\{114}\{95}\{115}\{104}\{111}\{119}\{108}\{105}\{103}\{104}\{116}", 0);
+       CHECKFAIL_ASSERT(5, cvar, "\{114}\{95}\{115}\{104}\{111}\{119}\{115}\{104}\{97}\{100}\{111}\{119}\{118}\{111}\{108}\{117}\{109}\{101}\{115}", 0);
+
        vf_size = R_SetView3fv(VF_SIZE);
        vf_min = R_SetView3fv(VF_MIN);
        vid_width = vf_size_x;
@@ -401,7 +421,7 @@ void CSQC_UpdateView(float w, float h)
        input_angles = warpzone_fixview_cl_viewangles;
        view_angles = warpzone_fixview_angles;
 
-       if(autocvar_cl_lockview || (autocvar__hud_configure && spectatee_status <= 0))
+       if(autocvar_cl_lockview || (autocvar__hud_configure && spectatee_status <= 0) || intermission > 1)
        {
                pmove_org = freeze_pmove_org;
                input_angles = view_angles = freeze_input_angles;
@@ -412,8 +432,44 @@ void CSQC_UpdateView(float w, float h)
        freeze_pmove_org = pmove_org;
        freeze_input_angles = input_angles;
 
+       // event chase camera
+       if(autocvar_chase_active <= 0) // greater than 0 means it's enabled manually, and this code is skipped
+       {
+               if(spectatee_status >= 0 && (autocvar_cl_eventchase_death && getstati(STAT_HEALTH) <= 0 && !intermission) || (autocvar_cl_eventchase_intermission && intermission))
+               {
+                       // We must enable chase_active to get a third person view (weapon viewmodel hidden and own player model showing).
+                       // Ideally, there should be another way to enable third person cameras, such as through R_SetView()
+                       if(!autocvar_chase_active)
+                               cvar_set("chase_active", "-1"); // -1 enables chase_active while marking it as set by this code, and not by the user (which would be 1)
+
+                       // make the camera smooth back
+                       if(autocvar_cl_eventchase_speed && eventchase_current_distance < autocvar_cl_eventchase_distance)
+                               eventchase_current_distance += autocvar_cl_eventchase_speed * (autocvar_cl_eventchase_distance - eventchase_current_distance) * frametime; // slow down the further we get
+                       else if(eventchase_current_distance != autocvar_cl_eventchase_distance)
+                               eventchase_current_distance = autocvar_cl_eventchase_distance;
+
+                       vector eventchase_target_origin;
+                       makevectors(view_angles);
+                       // pass 1, used to check where the camera would go and obtain the trace_fraction
+                       eventchase_target_origin = pmove_org - v_forward * eventchase_current_distance;
+
+                       traceline(pmove_org, eventchase_target_origin, MOVE_WORLDONLY, self);
+                       // pass 2, also multiplying view_forward with trace_fraction, to prevent the camera from going through walls
+                       // The 0.1 subtraction is to not limit the camera precisely at the wall surface, as that allows the view to poke through
+                       eventchase_target_origin = pmove_org - v_forward * eventchase_current_distance * (trace_fraction - 0.1);
+
+                       R_SetView(VF_ORIGIN, eventchase_target_origin);
+                       R_SetView(VF_ANGLES, view_angles);
+               }
+               else if(autocvar_chase_active < 0) // time to disable chase_active if it was set by this code
+               {
+                       cvar_set("chase_active", "0");
+                       eventchase_current_distance = 0; // start from 0 next time
+               }
+       }
+
        // Render the Scene
-       if(!intermission || !view_set)
+       if(!intermission || !view_set || (intermission && autocvar_cl_eventchase_intermission))
        {
                view_origin = pmove_org + vo;
                view_angles = input_angles;
@@ -468,22 +524,20 @@ void CSQC_UpdateView(float w, float h)
        carrierAnnouncer();
 
        fov = autocvar_fov;
-       if(button_zoom || fov <= 59.5)
+       if(fov <= 59.5)
        {
                if(!zoomscript_caught)
                {
-                       localcmd("+button4\n");
+                       localcmd("+button9\n");
                        zoomscript_caught = 1;
-                       ignore_plus_zoom += 1;
                }
        }
        else
        {
                if(zoomscript_caught)
                {
-                       localcmd("-button4\n");
+                       localcmd("-button9\n");
                        zoomscript_caught = 0;
-                       ignore_minus_zoom += 1;
                }
        }
 
@@ -557,10 +611,6 @@ void CSQC_UpdateView(float w, float h)
        // Draw the Engine Status Bar (the default Quake HUD)
        R_SetView(VF_DRAWENGINEHUD, 0);
 
-       // fetch this one only once per frame
-       hud_showbinds = autocvar_hud_showbinds;
-       hud_showbinds_limit = autocvar_hud_showbinds_limit;
-
        // Update the mouse position
        /*
           mousepos_x = vid_conwidth;
@@ -726,6 +776,22 @@ void CSQC_UpdateView(float w, float h)
                
                if(contentavgalpha)
                        drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, liquidcolor_prev, contentavgalpha * liquidalpha_prev, DRAWFLAG_NORMAL);
+
+               if(autocvar_hud_postprocessing)
+               {
+                       if(autocvar_hud_contents_blur && contentavgalpha)
+                       {
+                               content_blurpostprocess_x = 1;
+                               content_blurpostprocess_y = contentavgalpha * autocvar_hud_contents_blur;
+                               content_blurpostprocess_z = contentavgalpha * autocvar_hud_contents_blur_alpha;
+                       }
+                       else
+                       {
+                               content_blurpostprocess_x = 0;
+                               content_blurpostprocess_y = 0;
+                               content_blurpostprocess_z = 0;
+                       }
+               }
        }
        
        if(autocvar_hud_damage)
@@ -792,6 +858,74 @@ void CSQC_UpdateView(float w, float h)
                }
                else
                        drawpic(splash_pos, "gfx/blood", splash_size, stov(autocvar_hud_damage_color), bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage, DRAWFLAG_NORMAL);
+
+               if(autocvar_hud_postprocessing)
+               {
+                       if(autocvar_hud_damage_blur && myhealth_flash_temp)
+                       {
+                               damage_blurpostprocess_x = 1;
+                               damage_blurpostprocess_y = bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage_blur;
+                               damage_blurpostprocess_z = bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage_blur_alpha;
+                       }
+                       else
+                       {
+                               damage_blurpostprocess_x = 0;
+                               damage_blurpostprocess_y = 0;
+                               damage_blurpostprocess_z = 0;
+                       }
+               }
+       }
+
+       if(autocvar_hud_postprocessing)
+       {
+               // all of this should be done in the engine eventually
+
+               // enable or disable rendering types if they are used or not
+               if(cvar("r_glsl_postprocess_uservec1_enable") != (cvar("hud_postprocessing_maxbluralpha") != 0))
+                       cvar_set("r_glsl_postprocess_uservec1_enable", ftos(cvar("hud_postprocessing_maxbluralpha") != 0));
+               if(cvar("r_glsl_postprocess_uservec2_enable") != (cvar("hud_powerup") != 0))
+                       cvar_set("r_glsl_postprocess_uservec2_enable", ftos(cvar("hud_powerup") != 0));
+
+               // lets apply the postprocess effects from the previous two functions if needed
+               if((damage_blurpostprocess_x || content_blurpostprocess_x) && autocvar_chase_active >= 0) // not while the event chase camera is active
+               {
+                       float blurradius = bound(0, damage_blurpostprocess_y + content_blurpostprocess_y, autocvar_hud_postprocessing_maxblurradius);
+                       float bluralpha = bound(0, damage_blurpostprocess_z + content_blurpostprocess_z, autocvar_hud_postprocessing_maxbluralpha);
+                       if(blurradius != old_blurradius || bluralpha != old_bluralpha) // reduce cvar_set spam as much as possible
+                       {
+                               cvar_set("r_glsl_postprocess_uservec1", strcat(ftos(blurradius), " ", ftos(bluralpha), " 0 0"));
+                               old_blurradius = blurradius;
+                               old_bluralpha = bluralpha;
+                       }
+               }
+               else if(cvar_string("r_glsl_postprocess_uservec1") != "0 0 0 0") // reduce cvar_set spam as much as possible
+               {
+                       cvar_set("r_glsl_postprocess_uservec1", "0 0 0 0");
+                       old_blurradius = 0;
+                       old_bluralpha = 0;
+               }
+
+               float sharpen_intensity;
+               if (getstatf(STAT_STRENGTH_FINISHED) - time > 0)
+                       sharpen_intensity += (getstatf(STAT_STRENGTH_FINISHED) - time);
+               if (getstatf(STAT_INVINCIBLE_FINISHED) - time > 0)
+                       sharpen_intensity += (getstatf(STAT_INVINCIBLE_FINISHED) - time);
+
+               if(autocvar_hud_powerup && sharpen_intensity > 0 && autocvar_chase_active >= 0) // not while the event chase camera is active
+               {
+                       sharpen_intensity = bound(0, sharpen_intensity, 5); // powerup warning time is 5 seconds, so fade the effect from there
+
+                       if(sharpen_intensity != old_sharpen_intensity) // reduce cvar_set spam as much as possible
+                       {
+                               cvar_set("r_glsl_postprocess_uservec2", strcat("0 ", ftos(-sharpen_intensity * cvar("hud_powerup")), " 0 0"));
+                               old_sharpen_intensity = sharpen_intensity;
+                       }
+               }
+               else if(cvar_string("r_glsl_postprocess_uservec2") != "0 0 0 0") // reduce cvar_set spam as much as possible
+               {
+                       cvar_set("r_glsl_postprocess_uservec2", "0 0 0 0");
+                       old_sharpen_intensity = 0;
+               }
        }
 
        // Draw the mouse cursor
@@ -816,6 +950,7 @@ void CSQC_UpdateView(float w, float h)
                if(self.draw2d)
                        self.draw2d();
        self = e;
+       Draw_ShowNames_All();
 
        scoreboard_active = HUD_WouldDrawScoreboard();
 
@@ -858,7 +993,7 @@ void CSQC_UpdateView(float w, float h)
                                CSQC_common_hud();
 
                // crosshair goes VERY LAST
-               if(!scoreboard_active && !camera_active && intermission != 2) {
+               if(!scoreboard_active && !camera_active && intermission != 2 && spectatee_status != -1) {
                        string wcross_style;
                        float wcross_alpha, wcross_resolution;
                        wcross_style = autocvar_crosshair;
@@ -1096,7 +1231,7 @@ void CSQC_UpdateView(float w, float h)
                                        
 
                                // handle the values
-                               if (activeweapon == WEP_NEX && nex_charge && autocvar_crosshair_ring_nex) // ring around crosshair representing velocity-dependent damage for the nex
+                               if (autocvar_crosshair_ring && activeweapon == WEP_NEX && nex_charge && autocvar_crosshair_ring_nex) // ring around crosshair representing velocity-dependent damage for the nex
                                {
                                        if (nex_chargepool || use_nex_chargepool) { 
                                                use_nex_chargepool = 1; 
@@ -1116,7 +1251,7 @@ void CSQC_UpdateView(float w, float h)
                                        ring_rgb = wcross_color;
                                        ring_image = "gfx/crosshair_ring_nexgun.tga";
                                }
-                               else if (activeweapon == WEP_MINE_LAYER && minelayer_maxmines && autocvar_crosshair_ring_minelayer) 
+                               else if (autocvar_crosshair_ring && activeweapon == WEP_MINE_LAYER && minelayer_maxmines && autocvar_crosshair_ring_minelayer) 
                                {
                                        ring_value = bound(0, getstati(STAT_LAYED_MINES) / minelayer_maxmines, 1); // if you later need to use the count of bullets in another place, then add a float for it. For now, no need to.
                                        ring_alpha = autocvar_crosshair_ring_minelayer_alpha;
@@ -1125,7 +1260,7 @@ void CSQC_UpdateView(float w, float h)
                                }
                                else if (activeweapon == WEP_HAGAR && getstati(STAT_HAGAR_LOAD) && autocvar_crosshair_ring_hagar)
                                {
-                                       ring_value = bound(0, getstati(STAT_HAGAR_LOAD) / getstati(STAT_HAGAR_MAXLOAD), 1);
+                                       ring_value = bound(0, getstati(STAT_HAGAR_LOAD) / hagar_maxrockets, 1);
                                        ring_alpha = autocvar_crosshair_ring_hagar_alpha;
                                        ring_rgb = wcross_color;
                                        ring_image = "gfx/crosshair_ring.tga";
@@ -1557,7 +1692,6 @@ const float STAT_VEHICLESTAT_RELOAD2 = 66;
 
 }
 
-
 void CSQC_common_hud(void)
 {
        // HUD_SortFrags(); done in HUD_Draw