]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/client/view.qc
Merge branch 'master' into Lyberta/StandaloneOverkillWeapons
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / view.qc
index ae6b0ee7638ae0a3b36fc0b1e0e9a3b181ad4197..efdf2e108060e6b54753226af9fa0e09cd31bb73 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <common/vehicles/all.qh>
 #include <common/weapons/_all.qh>
+#include <common/mutators/mutator/overkill/okvortex.qh>
 #include <common/viewloc.qh>
 #include <common/minigames/cl_minigames.qh>
 #include <common/minigames/cl_minigames_hud.qh>
@@ -62,10 +63,9 @@ float autocvar_cl_leanmodel_highpass = 0.2;
 float autocvar_cl_leanmodel_lowpass = 0.05;
 
 #define avg_factor(avg_time) (1 - exp(-frametime / max(0.001, avg_time)))
-#define lowpass(value, frac, ref_store, ret) MACRO_BEGIN \
-{ \
-       ret = ref_store = ref_store * (1 - frac) + (value) * frac; \
-} MACRO_END
+
+#define lowpass(value, frac, ref_store, ret) \
+       ret = ref_store = ref_store * (1 - frac) + (value) * frac;
 
 #define lowpass_limited(value, frac, limit, ref_store, ret) MACRO_BEGIN \
 { \
@@ -326,7 +326,7 @@ void viewmodel_draw(entity this)
                        this.viewmodel_angles = this.angles;
                }
                anim_update(this);
-               if (!this.animstate_override && !this.animstate_looping)
+               if ((!this.animstate_override && !this.animstate_looping) || time > this.animstate_endtime)
                        anim_set(this, this.anim_idle, true, false, false);
        }
        float f = 0; // 0..1; 0: fully active
@@ -356,6 +356,7 @@ void viewmodel_draw(entity this)
        this.angles = this.viewmodel_angles;
        this.angles_x = (-90 * f * f);
        viewmodel_animate(this);
+       MUTATOR_CALLHOOK(DrawViewModel, this);
        setorigin(this, this.origin);
 }
 
@@ -466,7 +467,7 @@ vector GetCurrentFov(float fov)
                {
                        entity wepent = viewmodels[slot];
                        if(wepent.switchweapon == wepent.activeweapon)
-                       if((wepent.activeweapon == WEP_VORTEX && !WEP_CVAR(vortex, secondary)) || (wepent.activeweapon == WEP_RIFLE && !WEP_CVAR(rifle, secondary))) // do NOT use switchweapon here
+                       if((wepent.activeweapon == WEP_VORTEX && !WEP_CVAR(vortex, secondary)) || (wepent.activeweapon == WEP_RIFLE && !WEP_CVAR(rifle, secondary)) || (wepent.activeweapon == WEP_OVERKILL_VORTEX && !WEP_CVAR(okvortex, secondary))) // do NOT use switchweapon here
                                zoomdir += button_attack2;
                }
        }
@@ -522,7 +523,7 @@ vector GetCurrentFov(float fov)
                current_zoomfraction = (current_viewzoom - 1) / (1/zoomfactor - 1);
 
        if(zoomsensitivity < 1)
-               setsensitivityscale(pow(current_viewzoom, 1 - zoomsensitivity));
+               setsensitivityscale(current_viewzoom ** (1 - zoomsensitivity));
        else
                setsensitivityscale(1);
 
@@ -658,6 +659,7 @@ float TrueAimCheck(entity wepent)
                case WEP_MORTAR: // toss curve
                        return SHOTTYPE_HITWORLD;
                case WEP_VORTEX:
+               case WEP_OVERKILL_VORTEX:
                case WEP_VAPORIZER:
                        mv = MOVE_NORMAL;
                        break;
@@ -769,6 +771,8 @@ bool WantEventchase(entity this)
                        return true;
                if(MUTATOR_CALLHOOK(WantEventchase, this))
                        return true;
+               if(autocvar_cl_eventchase_frozen && STAT(FROZEN))
+                       return true;
                if(autocvar_cl_eventchase_death && (STAT(HEALTH) <= 0))
                {
                        if(autocvar_cl_eventchase_death == 2)
@@ -875,6 +879,14 @@ void HitSound()
                sound(NULL, CH_INFO, SND_TYPEHIT, VOL_BASE, ATTN_NONE);
                typehit_time_prev = typehit_time;
        }
+
+       static float kill_time_prev = 0;
+       float kill_time = STAT(KILL_TIME);
+       if (COMPARE_INCREASING(kill_time, kill_time_prev) > autocvar_cl_hitsound_antispam_time)
+       {
+               sound(NULL, CH_INFO, SND_KILL, VOL_BASE, ATTN_NONE);
+               kill_time_prev = kill_time;
+       }
 }
 
 vector crosshair_getcolor(entity this, float health_stat)
@@ -1172,6 +1184,10 @@ void HUD_Crosshair(entity this)
                                vortex_charge = STAT(VORTEX_CHARGE);
                                vortex_chargepool = STAT(VORTEX_CHARGEPOOL);
 
+                               float okvortex_charge, okvortex_chargepool;
+                               okvortex_charge = STAT(OVERKILL_VORTEX_CHARGE);
+                               okvortex_chargepool = STAT(OVERKILL_VORTEX_CHARGEPOOL);
+
                                float arc_heat = STAT(ARC_HEAT);
 
                                if(vortex_charge_movingavg == 0) // this should only happen if we have just loaded up the game
@@ -1191,7 +1207,7 @@ void HUD_Crosshair(entity this)
                                        }
 
                                        ring_inner_alpha = autocvar_crosshair_ring_vortex_inner_alpha;
-                                       ring_inner_rgb = eX * autocvar_crosshair_ring_vortex_inner_color_red + eY * autocvar_crosshair_ring_vortex_inner_color_green + eZ * autocvar_crosshair_ring_vortex_inner_color_blue;
+                                       ring_inner_rgb = vec3(autocvar_crosshair_ring_vortex_inner_color_red, autocvar_crosshair_ring_vortex_inner_color_green, autocvar_crosshair_ring_vortex_inner_color_blue);
                                        ring_inner_image = "gfx/crosshair_ring_inner.tga";
 
                                        // draw the outer ring to show the current charge of the weapon
@@ -1200,6 +1216,26 @@ void HUD_Crosshair(entity this)
                                        ring_rgb = wcross_color;
                                        ring_image = "gfx/crosshair_ring_nexgun.tga";
                                }
+                               else if (autocvar_crosshair_ring && (wepent.activeweapon == WEP_OVERKILL_VORTEX) && okvortex_charge && autocvar_crosshair_ring_vortex)
+                               {
+                                       if (okvortex_chargepool || use_vortex_chargepool) {
+                                               use_vortex_chargepool = 1;
+                                               ring_inner_value = okvortex_chargepool;
+                                       } else {
+                                               vortex_charge_movingavg = (1 - autocvar_crosshair_ring_vortex_currentcharge_movingavg_rate) * vortex_charge_movingavg + autocvar_crosshair_ring_vortex_currentcharge_movingavg_rate * okvortex_charge;
+                                               ring_inner_value = bound(0, autocvar_crosshair_ring_vortex_currentcharge_scale * (okvortex_charge - vortex_charge_movingavg), 1);
+                                       }
+
+                                       ring_inner_alpha = autocvar_crosshair_ring_vortex_inner_alpha;
+                                       ring_inner_rgb = eX * autocvar_crosshair_ring_vortex_inner_color_red + eY * autocvar_crosshair_ring_vortex_inner_color_green + eZ * autocvar_crosshair_ring_vortex_inner_color_blue;
+                                       ring_inner_image = "gfx/crosshair_ring_inner.tga";
+
+                                       // draw the outer ring to show the current charge of the weapon
+                                       ring_value = okvortex_charge;
+                                       ring_alpha = autocvar_crosshair_ring_vortex_alpha;
+                                       ring_rgb = wcross_color;
+                                       ring_image = "gfx/crosshair_ring_nexgun.tga";
+                               }
                                else if (autocvar_crosshair_ring && wepent.activeweapon == WEP_MINE_LAYER && WEP_CVAR(minelayer, limit) && autocvar_crosshair_ring_minelayer)
                                {
                                        ring_value = bound(0, STAT(LAYED_MINES) / WEP_CVAR(minelayer, limit), 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.
@@ -1346,31 +1382,40 @@ void HUD_Draw(entity this)
        if(!gametype)
                return;
 
+       Hud_Dynamic_Frame();
+
        if(!intermission)
        if (MUTATOR_CALLHOOK(HUD_Draw_overlay))
        {
-               drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, M_ARGV(0, vector), autocvar_hud_colorflash_alpha * M_ARGV(1, float), DRAWFLAG_ADDITIVE);
+               drawfill('0 0 0', vec2(vid_conwidth, vid_conheight), M_ARGV(0, vector), autocvar_hud_colorflash_alpha * M_ARGV(1, float), DRAWFLAG_ADDITIVE);
        }
        else if(STAT(FROZEN))
        {
-               drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, ((STAT(REVIVE_PROGRESS)) ? ('0.25 0.90 1' + ('1 0 0' * STAT(REVIVE_PROGRESS)) + ('0 1 1' * STAT(REVIVE_PROGRESS) * -1)) : '0.25 0.90 1'), autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
+               vector col = '0.25 0.90 1';
+               if(STAT(REVIVE_PROGRESS))
+                       col += vec3(STAT(REVIVE_PROGRESS), -STAT(REVIVE_PROGRESS), -STAT(REVIVE_PROGRESS));
+               drawfill('0 0 0', vec2(vid_conwidth, vid_conheight), col, autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
        }
+
+       HUD_Scale_Enable();
        if(!intermission)
        if(STAT(NADE_TIMER) && autocvar_cl_nade_timer) // give nade top priority, as it's a matter of life and death
        {
-               DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", STAT(NADE_TIMER), '0.25 0.90 1' + ('1 0 0' * STAT(NADE_TIMER)) - ('0 1 1' * STAT(NADE_TIMER)), autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
-               drawstring_aspect(eY * 0.64 * vid_conheight, ((autocvar_cl_nade_timer == 2) ? _("Nade timer") : ""), eX * vid_conwidth + eY * 0.025 * vid_conheight, '1 1 1', 1, DRAWFLAG_NORMAL);
+               vector col = '0.25 0.90 1' + vec3(STAT(NADE_TIMER), -STAT(NADE_TIMER), -STAT(NADE_TIMER));
+               DrawCircleClippedPic(vec2(0.5 * vid_conwidth, 0.6 * vid_conheight), 0.1 * vid_conheight, "gfx/crosshair_ring.tga", STAT(NADE_TIMER), col, autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
+               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);
        }
        else if(STAT(CAPTURE_PROGRESS))
        {
-               DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", STAT(CAPTURE_PROGRESS), '0.25 0.90 1', autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
-               drawstring_aspect(eY * 0.64 * vid_conheight, _("Capture progress"), eX * vid_conwidth + eY * 0.025 * vid_conheight, '1 1 1', 1, DRAWFLAG_NORMAL);
+               DrawCircleClippedPic(vec2(0.5 * vid_conwidth, 0.6 * vid_conheight), 0.1 * vid_conheight, "gfx/crosshair_ring.tga", STAT(CAPTURE_PROGRESS), '0.25 0.90 1', autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
+               drawstring_aspect(eY * 0.64 * vid_conheight, _("Capture progress"), vec2(vid_conwidth, 0.025 * vid_conheight), '1 1 1', 1, DRAWFLAG_NORMAL);
        }
        else if(STAT(REVIVE_PROGRESS))
        {
-               DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", STAT(REVIVE_PROGRESS), '0.25 0.90 1', autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
-               drawstring_aspect(eY * 0.64 * vid_conheight, _("Revival progress"), eX * vid_conwidth + eY * 0.025 * vid_conheight, '1 1 1', 1, DRAWFLAG_NORMAL);
+               DrawCircleClippedPic(vec2(0.5 * vid_conwidth, 0.6 * vid_conheight), 0.1 * vid_conheight, "gfx/crosshair_ring.tga", STAT(REVIVE_PROGRESS), '0.25 0.90 1', autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
+               drawstring_aspect(eY * 0.64 * vid_conheight, _("Revival progress"), vec2(vid_conwidth, 0.025 * vid_conheight), '1 1 1', 1, DRAWFLAG_NORMAL);
        }
+       HUD_Scale_Disable();
 
        if(autocvar_r_letterbox == 0)
                if(autocvar_viewsize < 120)
@@ -1735,7 +1780,7 @@ void CSQC_UpdateView(entity this, float w, float h)
 
                t = (time - blurtest_time0) / (blurtest_time1 - blurtest_time0);
                r = t * blurtest_radius;
-               f = 1 / pow(t, blurtest_power) - 1;
+               f = 1 / (t ** blurtest_power) - 1;
 
                cvar_set("r_glsl_postprocess", "1");
                cvar_set("r_glsl_postprocess_uservec1", strcat(ftos(r), " ", ftos(f), " 0 0"));
@@ -2014,7 +2059,7 @@ void CSQC_UpdateView(entity this, float w, float h)
                                switch(reticle_type)
                                {
                                        case 1: drawpic(reticle_pos, "gfx/reticle_normal", reticle_size, '1 1 1', f * autocvar_cl_reticle_normal_alpha, DRAWFLAG_NORMAL); break;
-                                       case 2: drawpic(reticle_pos, reticle_image, reticle_size, '1 1 1', f * autocvar_cl_reticle_weapon_alpha, DRAWFLAG_NORMAL); break;
+                                       case 2: if(reticle_image) drawpic(reticle_pos, reticle_image, reticle_size, '1 1 1', f * autocvar_cl_reticle_weapon_alpha, DRAWFLAG_NORMAL); break;
                                }
                        }
                }
@@ -2071,7 +2116,7 @@ void CSQC_UpdateView(entity this, float w, float h)
                contentavgalpha = contentavgalpha * (1 - contentalpha_temp) + incontent * contentalpha_temp;
 
                if(contentavgalpha)
-                       drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, liquidcolor_prev, contentavgalpha * liquidalpha_prev, DRAWFLAG_NORMAL);
+                       drawfill('0 0 0', vec2(vid_conwidth, vid_conheight), liquidcolor_prev, contentavgalpha * liquidalpha_prev, DRAWFLAG_NORMAL);
 
                if(autocvar_hud_postprocessing)
                {
@@ -2147,13 +2192,13 @@ void CSQC_UpdateView(entity this, float w, float h)
                        if(autocvar_cl_gentle_damage == 2)
                        {
                                if(myhealth_flash < pain_threshold) // only randomize when the flash is gone
-                                       myhealth_gentlergb = eX * random() + eY * random() + eZ * random();
+                                       myhealth_gentlergb = randomvec();
                        }
                        else
                                myhealth_gentlergb = stov(autocvar_hud_damage_gentle_color);
 
                        if(myhealth_flash_temp > 0)
-                               drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, myhealth_gentlergb, autocvar_hud_damage_gentle_alpha_multiplier * bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage, DRAWFLAG_NORMAL);
+                               drawfill('0 0 0', vec2(vid_conwidth, vid_conheight), myhealth_gentlergb, autocvar_hud_damage_gentle_alpha_multiplier * bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage, DRAWFLAG_NORMAL);
                }
                else if(myhealth_flash_temp > 0)
                        drawpic(splash_pos, "gfx/blood", splash_size, stov(autocvar_hud_damage_color), bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage, DRAWFLAG_NORMAL);
@@ -2237,7 +2282,9 @@ void CSQC_UpdateView(entity this, float w, float h)
        // draw 2D entities
        IL_EACH(g_drawables_2d, it.draw2d, it.draw2d(it));
        Draw_ShowNames_All();
+#ifdef DEBUGDRAW
        Debug_Draw();
+#endif
 
        scoreboard_active = Scoreboard_WouldDraw();