]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/client/view.qc
Merge branch 'master' into Mario/wepent_experimental
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / view.qc
index 98bd49dea30c35ee5577c1b929a76d1560255215..b98e5df0fce34fbdf7e09164196cf87ceb64e4c6 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>
@@ -312,6 +315,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)
                {
@@ -354,7 +360,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 +375,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)
+               vector pos = view_origin;
+               vector dir = view_forward;
+               if (wepent.angles_held_status)
                {
-                       n += 1;
-                       continue;
+                       makevectors(wepent.angles_held);
+                       dir = v_forward;
                }
-               if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
-               {
-                       n = max(2, idx);
-                       break;
-               }
-               // 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);
        }
 }
 
@@ -628,7 +637,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 +650,6 @@ float TrueAimCheck()
        ta = trueaim;
        mv = MOVE_NOMONSTERS;
 
-       entity wepent = viewmodels[0]; // TODO: unhardcode
-
        switch(wepent.activeweapon) // WEAPONTODO
        {
                case WEP_TUBA: // no aim
@@ -817,11 +824,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 +844,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)
@@ -883,7 +897,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 +905,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
                        {
@@ -985,8 +999,9 @@ void HUD_Crosshair(entity this)
                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;
@@ -1154,10 +1169,6 @@ void HUD_Crosshair(entity this)
                                weapon_clipload = STAT(WEAPON_CLIPLOAD);
                                weapon_clipsize = STAT(WEAPON_CLIPSIZE);
 
-                               float ok_ammo_charge, ok_ammo_chargepool;
-                               ok_ammo_charge = STAT(OK_AMMO_CHARGE);
-                               ok_ammo_chargepool = STAT(OK_AMMO_CHARGEPOOL);
-
                                float vortex_charge, vortex_chargepool;
                                vortex_charge = STAT(VORTEX_CHARGE);
                                vortex_chargepool = STAT(VORTEX_CHARGEPOOL);
@@ -1204,13 +1215,6 @@ void HUD_Crosshair(entity this)
                                        ring_rgb = wcross_color;
                                        ring_image = "gfx/crosshair_ring.tga";
                                }
-                               else if (ok_ammo_charge)
-                               {
-                                       ring_value = ok_ammo_chargepool;
-                                       ring_alpha = autocvar_crosshair_ring_reload_alpha;
-                                       ring_rgb = wcross_color;
-                                       ring_image = "gfx/crosshair_ring.tga";
-                               }
                                else if(autocvar_crosshair_ring_reload && weapon_clipsize) // forces there to be only an ammo ring
                                {
                                        ring_value = bound(0, weapon_clipload / weapon_clipsize, 1);
@@ -1793,33 +1797,36 @@ void CSQC_UpdateView(entity this, float w, float h)
 
        ColorTranslateMode = autocvar_cl_stripcolorcodes;
 
-       entity wepent = viewmodels[0]; // TODO: unhardcode
-
-       if(last_switchweapon != wepent.switchweapon)
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
        {
-               weapontime = time;
-               last_switchweapon = wepent.switchweapon;
-               if(button_zoom && autocvar_cl_unpress_zoom_on_weapon_switch)
+               entity wepent = viewmodels[slot];
+
+               if(wepent.last_switchweapon != wepent.switchweapon)
                {
-                       localcmd("-zoom\n");
-                       button_zoom = false;
+                       weapontime = time;
+                       wepent.last_switchweapon = wepent.switchweapon;
+                       if(slot == 0 && button_zoom && autocvar_cl_unpress_zoom_on_weapon_switch)
+                       {
+                               localcmd("-zoom\n");
+                               button_zoom = false;
+                       }
+                       if(slot == 0 && autocvar_cl_unpress_attack_on_weapon_switch)
+                       {
+                               localcmd("-fire\n");
+                               localcmd("-fire2\n");
+                               button_attack2 = false;
+                       }
                }
-               if(autocvar_cl_unpress_attack_on_weapon_switch)
+               if(wepent.last_activeweapon != wepent.activeweapon)
                {
-                       localcmd("-fire\n");
-                       localcmd("-fire2\n");
-                       button_attack2 = false;
-               }
-       }
-       if(last_activeweapon != wepent.activeweapon)
-       {
-               last_activeweapon = wepent.activeweapon;
+                       wepent.last_activeweapon = wepent.activeweapon;
 
-               e = wepent.activeweapon;
-               if(e.netname != "")
-                       localcmd(strcat("\ncl_hook_activeweapon ", e.netname), "\n");
-               else
-                       localcmd("\ncl_hook_activeweapon none\n");
+                       e = wepent.activeweapon;
+                       if(e.netname != "")
+                               localcmd(strcat("\ncl_hook_activeweapon ", e.netname), "\n");
+                       else if(slot == 0)
+                               localcmd("\ncl_hook_activeweapon none\n");
+               }
        }
 
        // ALWAYS Clear Current Scene First
@@ -1947,7 +1954,7 @@ void CSQC_UpdateView(entity this, float w, float h)
 
        if(autocvar_cl_reticle)
        {
-               string reticle_image = wepent.activeweapon.w_reticle;
+               string reticle_image = "";
                bool wep_zoomed = false;
                for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
                {
@@ -1956,7 +1963,8 @@ void CSQC_UpdateView(entity this, float w, float h)
                        if(wep != WEP_Null && wep.wr_zoom)
                        {
                                bool do_zoom = wep.wr_zoom(wep, NULL);
-                               reticle_image = wep.w_reticle;
+                               if(wep.w_reticle && wep.w_reticle != "")
+                                       reticle_image = wep.w_reticle;
                                wep_zoomed += do_zoom;
                        }
                }