]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/client/view.qc
Merge branch 'master' into Mario/killsound
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / view.qc
index 93c632e70fe250c34971c21f8d6fbad491becd41..65df30fd89ff5ec10f4eb3804cac9e7d3776c384 100644 (file)
@@ -13,6 +13,7 @@
 #include <common/ent_cs.qh>
 #include <common/anim.qh>
 #include <common/constants.qh>
+#include <common/net_linked.qh>
 #include <common/debug.qh>
 #include <common/mapinfo.qh>
 #include <common/gamemodes/_mod.qh>
@@ -21,6 +22,8 @@
 #include <common/triggers/target/music.qh>
 #include <common/teams.qh>
 
+#include <common/weapons/weapon/tuba.qh>
+
 #include <common/vehicles/all.qh>
 #include <common/weapons/_all.qh>
 #include <common/viewloc.qh>
@@ -122,7 +125,6 @@ void calc_followmodel_ofs(entity view)
        float frac;
        vector gunorg = '0 0 0';
        static vector vel_average;
-       static vector gunorg_prev = '0 0 0';
        static vector gunorg_adjustment_highpass;
        static vector gunorg_adjustment_lowpass;
 
@@ -312,6 +314,9 @@ void viewmodel_draw(entity this)
        }
        {
                string name = wep.mdl;
+               string newname = wep.wr_viewmodel(wep, this);
+               if(newname)
+                       name = newname;
                bool swap = name != this.name_last;
                // if (swap)
                {
@@ -321,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
@@ -354,7 +359,6 @@ void viewmodel_draw(entity this)
        setorigin(this, this.origin);
 }
 
-entity viewmodels[MAX_WEAPONSLOTS];
 STATIC_INIT(viewmodel) {
     for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
        viewmodels[slot] = new(viewmodel);
@@ -370,66 +374,70 @@ STATIC_INIT(Porto)
 }
 
 const int polyline_length = 16;
-vector polyline[polyline_length];
+.vector polyline[polyline_length];
 void Porto_Draw(entity this)
 {
-       entity wepent = viewmodels[0]; // TODO: unhardcode
-       if (wepent.activeweapon != WEP_PORTO) return;
-       if (spectatee_status) return;
-       if (WEP_CVAR(porto, secondary)) return;
-       if (intermission == 1) return;
-       if (intermission == 2) return;
-       if (STAT(HEALTH) <= 0) return;
-
-       vector pos = view_origin;
-       vector dir = view_forward;
-       if (angles_held_status)
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
        {
-               makevectors(angles_held);
-               dir = v_forward;
-       }
+               entity wepent = viewmodels[slot];
 
-       polyline[0] = pos;
+               if (wepent.activeweapon != WEP_PORTO) continue;
+               if (spectatee_status) continue;
+               if (WEP_CVAR(porto, secondary)) continue;
+               if (intermission == 1) continue;
+               if (intermission == 2) continue;
+               if (STAT(HEALTH) <= 0) continue;
 
-       int portal_number = 0, portal1_idx = 1, portal_max = 2;
-       int n = 1 + 2;  // 2 lines == 3 points
-       for (int idx = 0; idx < n && idx < polyline_length - 1; )
-       {
-               traceline(pos, pos + 65536 * dir, true, this);
-               dir = reflect(dir, trace_plane_normal);
-               pos = trace_endpos;
-               polyline[++idx] = pos;
-               if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP)
-               {
-                       n += 1;
-                       continue;
-               }
-               if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
+               vector pos = view_origin;
+               vector dir = view_forward;
+               if (wepent.angles_held_status)
                {
-                       n = max(2, idx);
-                       break;
+                       makevectors(wepent.angles_held);
+                       dir = v_forward;
                }
-               // check size
+
+               wepent.polyline[0] = pos;
+
+               int portal_number = 0, portal1_idx = 1, portal_max = 2;
+               int n = 1 + 2;  // 2 lines == 3 points
+               for (int idx = 0; idx < n && idx < polyline_length - 1; )
                {
-                       vector ang = vectoangles2(trace_plane_normal, dir);
-                       ang.x = -ang.x;
-                       makevectors(ang);
-                       if (!CheckWireframeBox(this, pos - 48 * v_right - 48 * v_up + 16 * v_forward, 96 * v_right, 96 * v_up, 96 * v_forward))
+                       traceline(pos, pos + 65536 * dir, true, this);
+                       dir = reflect(dir, trace_plane_normal);
+                       pos = trace_endpos;
+                       wepent.polyline[++idx] = pos;
+                       if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP)
+                       {
+                               n += 1;
+                               continue;
+                       }
+                       if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
                        {
                                n = max(2, idx);
                                break;
                        }
+                       // check size
+                       {
+                               vector ang = vectoangles2(trace_plane_normal, dir);
+                               ang.x = -ang.x;
+                               makevectors(ang);
+                               if (!CheckWireframeBox(this, pos - 48 * v_right - 48 * v_up + 16 * v_forward, 96 * v_right, 96 * v_up, 96 * v_forward))
+                               {
+                                       n = max(2, idx);
+                                       break;
+                               }
+                       }
+                       portal_number += 1;
+                       if (portal_number >= portal_max) break;
+                       if (portal_number == 1) portal1_idx = idx;
+               }
+               for (int idx = 0; idx < n - 1; ++idx)
+               {
+                       vector p = wepent.polyline[idx], q = wepent.polyline[idx + 1];
+                       if (idx == 0) p -= view_up * 16;  // line from player
+                       vector rgb = (idx < portal1_idx) ? '1 0 0' : '0 0 1';
+                       Draw_CylindricLine(p, q, 4, "", 1, 0, rgb, 0.5, DRAWFLAG_NORMAL, view_origin);
                }
-               portal_number += 1;
-               if (portal_number >= portal_max) break;
-               if (portal_number == 1) portal1_idx = idx;
-       }
-       for (int idx = 0; idx < n - 1; ++idx)
-       {
-               vector p = polyline[idx], q = polyline[idx + 1];
-               if (idx == 0) p -= view_up * 16;  // line from player
-               vector rgb = (idx < portal1_idx) ? '1 0 0' : '0 0 1';
-               Draw_CylindricLine(p, q, 4, "", 1, 0, rgb, 0.5, DRAWFLAG_NORMAL, view_origin);
        }
 }
 
@@ -514,7 +522,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);
 
@@ -628,7 +636,7 @@ float EnemyHitCheck()
        return SHOTTYPE_HITENEMY;
 }
 
-float TrueAimCheck()
+float TrueAimCheck(entity wepent)
 {
        float nudge = 1; // added to traceline target and subtracted from result TOOD(divVerent): do we still need this? Doesn't the engine do this now for us?
        vector vecs, trueaimpoint, w_shotorg;
@@ -641,8 +649,6 @@ float TrueAimCheck()
        ta = trueaim;
        mv = MOVE_NOMONSTERS;
 
-       entity wepent = viewmodels[0]; // TODO: unhardcode
-
        switch(wepent.activeweapon) // WEAPONTODO
        {
                case WEP_TUBA: // no aim
@@ -660,7 +666,7 @@ float TrueAimCheck()
                        mv = MOVE_NORMAL;
                        if(zoomscript_caught)
                        {
-                               tracebox(view_origin, '0 0 0', '0 0 0', view_origin + view_forward * MAX_SHOT_DISTANCE, mv, ta);
+                               tracebox(view_origin, '0 0 0', '0 0 0', view_origin + view_forward * max_shot_distance, mv, ta);
                                return EnemyHitCheck();
                        }
                        break;
@@ -686,7 +692,7 @@ float TrueAimCheck()
 
        vecs = decompressShotOrigin(STAT(SHOTORG));
 
-       traceline(traceorigin, traceorigin + view_forward * MAX_SHOT_DISTANCE, mv, ta);
+       traceline(traceorigin, traceorigin + view_forward * max_shot_distance, mv, ta);
        trueaimpoint = trace_endpos;
 
        if(vdist((trueaimpoint - traceorigin), <, g_trueaim_minrange))
@@ -753,7 +759,7 @@ bool WantEventchase(entity this)
 {
        if(autocvar_cl_orthoview)
                return false;
-       if(intermission)
+       if(STAT(GAME_STOPPED) || intermission)
                return true;
        if(this.viewloc)
                return true;
@@ -817,11 +823,18 @@ void HitSound()
 {
        // varying sound pitch
 
-       entity wepent = viewmodels[0]; // TODO: unhardcode
+       bool have_arc = false;
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               entity wepent = viewmodels[slot];
+
+               if(wepent.activeweapon == WEP_ARC)
+                       have_arc = true;
+       }
 
        static float hitsound_time_prev = 0;
        // HACK: the only way to get the arc to sound consistent with pitch shift is to ignore cl_hitsound_antispam_time
-       float arc_hack = wepent.activeweapon == WEP_ARC && autocvar_cl_hitsound >= 2;
+       bool arc_hack = have_arc && autocvar_cl_hitsound >= 2;
        if (arc_hack || COMPARE_INCREASING(time, hitsound_time_prev) > autocvar_cl_hitsound_antispam_time)
        {
                if (autocvar_cl_hitsound && unaccounted_damage)
@@ -830,8 +843,8 @@ void HitSound()
                        float a = autocvar_cl_hitsound_max_pitch;
                        float b = autocvar_cl_hitsound_min_pitch;
                        float c = autocvar_cl_hitsound_nom_damage;
-                       float x = unaccounted_damage;
-                       float pitch_shift = (b*x*(a-1) + a*c*(1-b)) / (x*(a-1) + c*(1-b));
+                       float d = unaccounted_damage;
+                       float pitch_shift = (b*d*(a-1) + a*c*(1-b)) / (d*(a-1) + c*(1-b));
 
                        // if sound variation is disabled, set pitch_shift to 1
                        if (autocvar_cl_hitsound == 1)
@@ -862,6 +875,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)
@@ -883,7 +904,7 @@ vector crosshair_getcolor(entity this, float health_stat)
 
                case 2: // crosshair_color_by_health
                {
-                       float x = health_stat;
+                       float hp = health_stat;
 
                        //x = red
                        //y = green
@@ -891,33 +912,33 @@ vector crosshair_getcolor(entity this, float health_stat)
 
                        wcross_color.z = 0;
 
-                       if(x > 200)
+                       if(hp > 200)
                        {
                                wcross_color.x = 0;
                                wcross_color.y = 1;
                        }
-                       else if(x > 150)
+                       else if(hp > 150)
                        {
-                               wcross_color.x = 0.4 - (x-150)*0.02 * 0.4;
-                               wcross_color.y = 0.9 + (x-150)*0.02 * 0.1;
+                               wcross_color.x = 0.4 - (hp-150)*0.02 * 0.4;
+                               wcross_color.y = 0.9 + (hp-150)*0.02 * 0.1;
                        }
-                       else if(x > 100)
+                       else if(hp > 100)
                        {
-                               wcross_color.x = 1 - (x-100)*0.02 * 0.6;
-                               wcross_color.y = 1 - (x-100)*0.02 * 0.1;
-                               wcross_color.z = 1 - (x-100)*0.02;
+                               wcross_color.x = 1 - (hp-100)*0.02 * 0.6;
+                               wcross_color.y = 1 - (hp-100)*0.02 * 0.1;
+                               wcross_color.z = 1 - (hp-100)*0.02;
                        }
-                       else if(x > 50)
+                       else if(hp > 50)
                        {
                                wcross_color.x = 1;
                                wcross_color.y = 1;
-                               wcross_color.z = 0.2 + (x-50)*0.02 * 0.8;
+                               wcross_color.z = 0.2 + (hp-50)*0.02 * 0.8;
                        }
-                       else if(x > 20)
+                       else if(hp > 20)
                        {
                                wcross_color.x = 1;
-                               wcross_color.y = (x-20)*90/27/100;
-                               wcross_color.z = (x-20)*90/27/100 * 0.2;
+                               wcross_color.y = (hp-20)*90/27/100;
+                               wcross_color.z = (hp-20)*90/27/100 * 0.2;
                        }
                        else
                        {
@@ -948,7 +969,7 @@ void HUD_Crosshair(entity this)
 {
        float f, i, j;
        vector v;
-       if(!scoreboard_active && !camera_active && intermission != 2 &&
+       if(!scoreboard_active && !camera_active && intermission != 2 && !STAT(GAME_STOPPED) &&
                spectatee_status != -1 && !csqcplayer.viewloc && !MUTATOR_CALLHOOK(DrawCrosshair) &&
                !HUD_MinigameMenu_IsOpened() )
        {
@@ -980,13 +1001,14 @@ void HUD_Crosshair(entity this)
                float shottype;
 
                // wcross_origin = '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
-               wcross_origin = project_3d_to_2d(view_origin + MAX_SHOT_DISTANCE * view_forward);
+               wcross_origin = project_3d_to_2d(view_origin + max_shot_distance * view_forward);
                wcross_origin.z = 0;
                if(autocvar_crosshair_hittest)
                {
                        vector wcross_oldorigin;
+                       entity thiswep = viewmodels[0]; // TODO: unhardcode
                        wcross_oldorigin = wcross_origin;
-                       shottype = TrueAimCheck();
+                       shottype = TrueAimCheck(thiswep);
                        if(shottype == SHOTTYPE_HITWORLD)
                        {
                                v = wcross_origin - wcross_oldorigin;
@@ -1721,7 +1743,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"));
@@ -1748,8 +1770,8 @@ void CSQC_UpdateView(entity this, float w, float h)
        if(!postinit)
                PostInit();
 
-       if(intermission && !gameover_time)
-               gameover_time = time;
+       if(intermission && !intermission_time)
+               intermission_time = time;
 
        if(intermission && !isdemo() && !(calledhooks & HOOK_END))
        {
@@ -1939,7 +1961,7 @@ void CSQC_UpdateView(entity this, float w, float h)
 
        if(autocvar_cl_reticle)
        {
-               string reticle_image = "";
+               string reticle_image = string_null;
                bool wep_zoomed = false;
                for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
                {
@@ -1948,7 +1970,7 @@ void CSQC_UpdateView(entity this, float w, float h)
                        if(wep != WEP_Null && wep.wr_zoom)
                        {
                                bool do_zoom = wep.wr_zoom(wep, NULL);
-                               if(wep.w_reticle && wep.w_reticle != "")
+                               if(!reticle_image && wep.w_reticle && wep.w_reticle != "")
                                        reticle_image = wep.w_reticle;
                                wep_zoomed += do_zoom;
                        }
@@ -1964,7 +1986,7 @@ void CSQC_UpdateView(entity this, float w, float h)
                }
                else if(wep_zoomed && autocvar_cl_reticle_weapon)
                {
-                       if(reticle_image && reticle_image != "") { reticle_type = 2; }
+                       if(reticle_image) { reticle_type = 2; }
                        else { reticle_type = 0; }
                }
                else if(button_zoom || zoomscript_caught)
@@ -2000,7 +2022,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;
                                }
                        }
                }