]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'martin-t/globals' into 'master'
authorMario <mario.mario@y7mail.com>
Sun, 29 Sep 2019 08:29:53 +0000 (08:29 +0000)
committerMario <mario.mario@y7mail.com>
Sun, 29 Sep 2019 08:29:53 +0000 (08:29 +0000)
Deglobalization - part 1

See merge request xonotic/xonotic-data.pk3dir!623

1  2 
qcsrc/client/view.qc
qcsrc/common/mutators/mutator/dodging/sv_dodging.qc
qcsrc/common/weapons/weapon/shockwave.qc
qcsrc/server/weapons/tracing.qc
qcsrc/server/weapons/weaponsystem.qc

diff --combined qcsrc/client/view.qc
index 5ae7d50056a64ba22ec96656873ba25eef86e5a6,dadf6069abfdad7010f7a8574366c87d843b0804..850217f152c1b8013399873762a5d4a0f3484fe6
@@@ -133,8 -133,8 +133,8 @@@ void calc_followmodel_ofs(entity view
                vel = view.velocity;
        else
        {
-               vector forward = '0 0 0', right = '0 0 0', up = '0 0 0';
-               MAKEVECTORS(makevectors, view_angles, forward, right, up);
+               vector forward, right, up;
+               MAKE_VECTORS(view_angles, forward, right, up);
                vel.x = view.velocity * forward;
                vel.y = view.velocity * right * -1;
                vel.z = view.velocity * up;
        if (autocvar_cl_followmodel_velocity_absolute)
        {
                vector fixed_gunorg;
-               vector forward = '0 0 0', right = '0 0 0', up = '0 0 0';
-               MAKEVECTORS(makevectors, view_angles, forward, right, up);
+               vector forward, right, up;
+               MAKE_VECTORS(view_angles, forward, right, up);
                fixed_gunorg.x = gunorg * forward;
                fixed_gunorg.y = gunorg * right * -1;
                fixed_gunorg.z = gunorg * up;
@@@ -291,7 -291,6 +291,7 @@@ void viewmodel_draw(entity this
                return;
        int mask = (intermission || (STAT(HEALTH) <= 0) || autocvar_chase_active) ? 0 : MASK_NORMAL;
        float a = ((autocvar_cl_viewmodel_alpha) ? bound(-1, autocvar_cl_viewmodel_alpha, this.m_alpha) : this.m_alpha);
 +      int wepskin = this.m_skin;
        bool invehicle = player_localentnum > maxclients;
        if (invehicle) a = -1;
        Weapon wep = this.activeweapon;
        {
                e.drawmask = mask;
                e.alpha = a;
 +              e.skin = wepskin;
                e.colormap = 256 + c;  // colormap == 0 is black, c == 0 is white
                e.glowmod = g;
                e.csqcmodel_effects = fx;
@@@ -493,15 -491,16 +493,16 @@@ vector GetCurrentFov(float fov
                        curspeed = 0;
                else
                {
-                       makevectors(view_angles);
+                       vector forward, right, up;
+                       MAKE_VECTORS(view_angles, forward, right, up);
                        v = pmove_vel;
                        if(csqcplayer)
                                v = csqcplayer.velocity;
  
                        switch(autocvar_cl_velocityzoom_type)
                        {
-                               case 3: curspeed = max(0, v_forward * v); break;
-                               case 2: curspeed = (v_forward * v); break;
+                               case 3: curspeed = max(0, forward * v); break;
+                               case 2: curspeed = (forward * v); break;
                                case 1: default: curspeed = vlen(v); break;
                        }
                }
@@@ -714,7 -713,7 +715,7 @@@ vector liquidcolor_prev
  
  float eventchase_current_distance;
  float eventchase_running;
 -int WantEventchase(entity this)
 +int WantEventchase(entity this, bool want_vehiclechase)
  {
        if(autocvar_cl_orthoview)
                return 0;
                return 1;
        if(spectatee_status >= 0)
        {
 -              if(hud != HUD_NORMAL && (autocvar_cl_eventchase_vehicle || spectatee_status > 0))
 +              if(want_vehiclechase)
                        return 1;
                if(MUTATOR_CALLHOOK(WantEventchase, this))
                        return 1;
@@@ -974,21 -973,6 +975,21 @@@ void HUD_Crosshair(entity this
                // wcross_origin = '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
                if(csqcplayer.viewloc && (csqcplayer.viewloc.spawnflags & VIEWLOC_FREEAIM))
                        wcross_origin = viewloc_mousepos;
 +              else if(autocvar_chase_active > 0 && autocvar_crosshair_chase)
 +              {
 +                      vector player_org = ((csqcplayer) ? csqcplayer.origin + csqcplayer.view_ofs : view_origin);
 +                      if(csqcplayer && crosshair_chase_playeralpha && crosshair_chase_playeralpha < 1)
 +                      {
 +                              traceline(view_origin, view_origin + max_shot_distance * view_forward, MOVE_NORMAL, NULL);
 +                              float myalpha = (!csqcplayer.m_alpha) ? 1 : csqcplayer.m_alpha;
 +                              if(trace_ent == csqcplayer && STAT(HEALTH) > 0)
 +                                      csqcplayer.alpha = min(crosshair_chase_playeralpha, myalpha);
 +                              else
 +                                      csqcplayer.alpha = csqcplayer.m_alpha;
 +                      }
 +                      traceline(player_org, player_org + max_shot_distance * view_forward, MOVE_WORLDONLY, NULL);
 +                      wcross_origin = project_3d_to_2d(trace_endpos);
 +              }
                else
                        wcross_origin = project_3d_to_2d(view_origin + max_shot_distance * view_forward);
                wcross_origin.z = 0;
                        wcross_color.z += sin(hitindication_crosshair_size) * hitindication_color.z;
                }
  
 -              if(shottype == SHOTTYPE_HITENEMY)
 -                      wcross_scale *= autocvar_crosshair_hittest; // is not queried if hittest is 0
 +              // no effects needed for targeting enemies, this can't possibly span all valid targets!
 +              // just show for teammates to give a sign that they're an invalid target
 +              //if(shottype == SHOTTYPE_HITENEMY)
 +                      //wcross_scale *= autocvar_crosshair_hittest; // is not queried if hittest is 0
                if(shottype == SHOTTYPE_HITTEAM)
                        wcross_scale /= autocvar_crosshair_hittest; // is not queried if hittest is 0
  
@@@ -1581,10 -1563,6 +1582,10 @@@ void CSQC_UpdateView(entity this, floa
  
        lasthud = hud;
  
 +      ReplicateVars(false);
 +      if (ReplicateVars_NOT_SENDING())
 +              ReplicateVars_DELAY(0.8 + random() * 0.4); // no need to check cvars every frame
 +
        HUD_Scale_Disable();
  
        if(autocvar__hud_showbinds_reload) // menu can set this one
                else if(autocvar_chase_active == -2)
                        cvar_set("chase_active", "0");
  
 -              float vehicle_chase = (hud != HUD_NORMAL && (autocvar_cl_eventchase_vehicle || spectatee_status > 0));
 +              bool vehicle_chase = (hud != HUD_NORMAL && (autocvar_cl_eventchase_vehicle || spectatee_status > 0));
  
                float vehicle_viewdist = 0;
                vector vehicle_viewofs = '0 0 0';
                                Vehicle info = Vehicles_from(hud);
                                vehicle_viewdist = info.height;
                                vehicle_viewofs = info.view_ofs;
 +                              if(vehicle_viewdist < 0) // when set below 0, this vehicle doesn't use third person view (gunner slots)
 +                                      vehicle_chase = false;
                        }
 +                      else
 +                              vehicle_chase = false;
                }
  
 -              int eventchase = WantEventchase(this);
 +              int eventchase = WantEventchase(this, vehicle_chase);
                if (eventchase)
                {
                        vector current_view_origin_override = '0 0 0';
                        else if(eventchase_current_distance != chase_distance)
                                eventchase_current_distance = chase_distance;
  
-                       makevectors(view_angles);
+                       vector forward, right, up;
+                       MAKE_VECTORS(view_angles, forward, right, up);
  
-                       vector eventchase_target_origin = (current_view_origin - (v_forward * eventchase_current_distance));
+                       vector eventchase_target_origin = (current_view_origin - (forward * eventchase_current_distance));
                        WarpZone_TraceBox(current_view_origin, autocvar_cl_eventchase_mins, autocvar_cl_eventchase_maxs, eventchase_target_origin, MOVE_WORLDONLY, this);
  
                        // If the boxtrace fails, revert back to line tracing.
                        if(!local_player.viewloc)
                        if(trace_startsolid)
                        {
-                               eventchase_target_origin = (current_view_origin - (v_forward * eventchase_current_distance));
+                               eventchase_target_origin = (current_view_origin - (forward * eventchase_current_distance));
                                WarpZone_TraceLine(current_view_origin, eventchase_target_origin, MOVE_WORLDONLY, this);
-                               setproperty(VF_ORIGIN, (trace_endpos - (v_forward * autocvar_cl_eventchase_mins.z)));
+                               setproperty(VF_ORIGIN, (trace_endpos - (forward * autocvar_cl_eventchase_mins.z)));
                        }
                        else { setproperty(VF_ORIGIN, trace_endpos); }
  
        // Render the Scene
        view_origin = getpropertyvec(VF_ORIGIN);
        view_angles = getpropertyvec(VF_ANGLES);
-       MAKEVECTORS(makevectors, view_angles, view_forward, view_right, view_up);
+       MAKE_VECTORS(view_angles, view_forward, view_right, view_up);
  
  #ifdef BLURTEST
        if(time > blurtest_time0 && time < blurtest_time1)
                setproperty(VF_ORIGIN, '0 0 0');
                setproperty(VF_ANGLES, '0 0 0');
                setproperty(VF_PERSPECTIVE, 1);
-               makevectors('0 0 0');
+               vector forward, right, up;
+               MAKE_VECTORS('0 0 0', forward, right, up);
                vector v1, v2;
                cvar_set("vid_conwidth", "800");
                cvar_set("vid_conheight", "600");
-               v1 = cs_project(v_forward);
+               v1 = cs_project(forward);
                cvar_set("vid_conwidth", "640");
                cvar_set("vid_conheight", "480");
-               v2 = cs_project(v_forward);
+               v2 = cs_project(forward);
                if(v1 == v2)
                        cs_project_is_b0rked = 1;
                else
index c97308d58ab1f8cd8a7db8adcd738c277baa739e,652f7a2b7b8e9aa7c4a19d7f5832cd769224aed2..66d18ac671e8ad9c5ce074c8f74eee7e494fb9f5
  #endif
  
  #ifdef CSQC
 +      float cvar_cl_dodging_timeout;
        #define PHYS_DODGING_FRAMETIME                          (1 / (frametime <= 0 ? 60 : frametime))
        #define PHYS_DODGING_TIMEOUT(s)                         STAT(DODGING_TIMEOUT)
        #define PHYS_DODGING_PRESSED_KEYS(s)            (s).pressedkeys
  #elif defined(SVQC)
 +      .float cvar_cl_dodging_timeout;
        #define PHYS_DODGING_FRAMETIME                          sys_frametime
        #define PHYS_DODGING_TIMEOUT(s)                         CS(s).cvar_cl_dodging_timeout
        #define PHYS_DODGING_PRESSED_KEYS(s)            CS(s).pressedkeys
@@@ -58,6 -56,8 +58,6 @@@ bool autocvar_sv_dodging_sound
  #include <common/animdecide.qh>
  #include <common/physics/player.qh>
  
 -.float cvar_cl_dodging_timeout;
 -
  REGISTER_MUTATOR(dodging, cvar("g_dodging"))
  {
        // this just turns on the cvar.
@@@ -113,20 -113,20 +113,20 @@@ REGISTER_MUTATOR(dodging, true)
                return true;
  
  // returns true if the player is close to a wall
- bool is_close_to_wall(entity this, float threshold)
+ bool is_close_to_wall(entity this, float threshold, vector forward, vector right)
  {
-       X(v_right);
-       X(-v_right);
-       X(v_forward);
-       X(-v_forward);
+       X(right);
+       X(-right);
+       X(forward);
+       X(-forward);
  
        return false;
  }
  
- bool is_close_to_ground(entity this, float threshold)
+ bool is_close_to_ground(entity this, float threshold, vector up)
  {
        if (IS_ONGROUND(this)) return true;
-       X(-v_up); // necessary for dodging down a slope using doubletap (using `+dodge` works anyway)
+       X(-up); // necessary for dodging down a slope using doubletap (using `+dodge` works anyway)
  
        return false;
  }
@@@ -180,10 -180,11 +180,11 @@@ bool PM_dodging_checkpressedkeys(entit
        if ((time - this.last_dodging_time) < PHYS_DODGING_DELAY)
                return false;
  
-       makevectors(this.angles);
+       vector forward, right, up;
+       MAKE_VECTORS(this.angles, forward, right, up);
  
-       bool can_dodge = (is_close_to_ground(this, PHYS_DODGING_HEIGHT_THRESHOLD) && (PHYS_DODGING_MAXSPEED == 0 || vdist(this.velocity, <, PHYS_DODGING_MAXSPEED)));
-       bool can_wall_dodge = (PHYS_DODGING_WALL && is_close_to_wall(this, PHYS_DODGING_DISTANCE_THRESHOLD));
+       bool can_dodge = (is_close_to_ground(this, PHYS_DODGING_HEIGHT_THRESHOLD, up) && (PHYS_DODGING_MAXSPEED == 0 || vdist(this.velocity, <, PHYS_DODGING_MAXSPEED)));
+       bool can_wall_dodge = (PHYS_DODGING_WALL && is_close_to_wall(this, PHYS_DODGING_DISTANCE_THRESHOLD, forward, right));
        bool can_air_dodge = (PHYS_DODGING_AIR && (PHYS_DODGING_AIR_MAXSPEED == 0 || vdist(this.velocity, <, PHYS_DODGING_AIR_MAXSPEED)));
        if (!can_dodge && !can_wall_dodge && !can_air_dodge) return false;
  
@@@ -221,11 -222,11 +222,11 @@@ void PM_dodging(entity this
                return;
        }
  
-       // make sure v_up, v_right and v_forward are sane
+       vector forward, right, up;
        if(PHYS_DODGING_AIR)
-               makevectors(this.v_angle);
+               MAKE_VECTORS(this.v_angle, forward, right, up);
        else
-               makevectors(this.angles);
+               MAKE_VECTORS(this.angles, forward, right, up);
  
        // fraction of the force to apply each frame
        // if we have e.g. 0.5 sec ramptime and a frametime of 0.25, then the ramp code
  
        float velocity_increase = min(common_factor * this.dodging_force_total, this.dodging_force_remaining);
        this.dodging_force_remaining -= velocity_increase;
-       this.velocity += this.dodging_direction.x * velocity_increase * v_forward
-                      + this.dodging_direction.y * velocity_increase * v_right;
+       this.velocity += this.dodging_direction.x * velocity_increase * forward
+                      + this.dodging_direction.y * velocity_increase * right;
  
        // the up part of the dodge is a single shot action
        if (this.dodging_single_action == 1)
        {
                UNSET_ONGROUND(this);
  
-               this.velocity += PHYS_DODGING_UP_SPEED * v_up;
+               this.velocity += PHYS_DODGING_UP_SPEED * up;
  
  #ifdef SVQC
                if (autocvar_sv_dodging_sound)
index 94f84ba5b1b8a88fa13b78e7c7afc7aed9f703a8,9b1dd6c0b8536b31029d7c87771d4806a6a9ee3b..74986f9cc96be069154ee8c5dd35419cf07c6b85
@@@ -3,8 -3,6 +3,8 @@@
  REGISTER_NET_TEMP(TE_CSQC_SHOCKWAVEPARTICLE)
  
  #ifdef SVQC
 +// enable when shockwave replaces shotgun
 +#if 0
  METHOD(Shockwave, m_spawnfunc_hookreplace, Weapon(Shockwave this, entity e))
  {
        //if(autocvar_sv_q3acompat_machineshockwaveswap) // WEAPONTODO
@@@ -14,7 -12,6 +14,7 @@@
        }
        return this;
  }
 +#endif
  
  const float MAX_SHOCKWAVE_HITS = 10;
  //#define DEBUG_SHOCKWAVE
@@@ -666,9 -663,8 +666,8 @@@ void Draw_Shockwave(entity this
        // WEAPONTODO: trace to find what we actually hit
        vector endpos = (this.sw_shotorg + (this.sw_shotdir * this.sw_distance));
  
-       vectorvectors(this.sw_shotdir);
-       vector right = v_right; // save this for when we do makevectors later
-       vector up = v_up; // save this for when we do makevectors later
+       vector _forward, right, up;
+       VECTOR_VECTORS(this.sw_shotdir, _forward, right, up);
  
        // WEAPONTODO: combine and simplify these calculations
        vector min_end = ((this.sw_shotorg + (this.sw_shotdir * SW_DISTTOMIN)) + (up * this.sw_spread_min));
index 06bebeba2746f09b57e3cc37e6f0c4c95075f5c5,ef7f1a832b6f77dc4b334b322931ad81e0a37930..6209710b6dea85697a40639ebc18c2d7f47d509b
@@@ -51,14 -51,14 +51,14 @@@ void W_SetupShot_Dir_ProjectileSize_Ran
                WarpZone_TraceLine(ent.origin + ent.view_ofs, ent.origin + ent.view_ofs + s_forward * range, MOVE_NOMONSTERS, ent);
        ent.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
  
-       vector vf, vr, vu;
-       vf = v_forward;
-       vr = v_right;
-       vu = v_up;
+       vector forward, right, up;
+       forward = v_forward;
+       right = v_right;
+       up = v_up;
        w_shotend = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos); // warpzone support
-       v_forward = vf;
-       v_right = vr;
-       v_up = vu;
+       v_forward = forward;
+       v_right = right;
+       v_up = up;
  
        // un-adjust trueaim if shotend is too close
        if(vdist(w_shotend - (ent.origin + ent.view_ofs), <, autocvar_g_trueaim_minrange))
                accuracy_add(ent, wep, maxdamage, 0);
  
        if(IS_PLAYER(ent))
-               W_HitPlotAnalysis(ent, wep, v_forward, v_right, v_up);
+               W_HitPlotAnalysis(ent, wep, forward, right, up);
  
        vector md = ent.(weaponentity).movedir;
        vector vecs = ((md.x > 0) ? md : '0 0 0');
  
        // TODO this is broken - see 637056bea7bf7f5c9c0fc6113e94731a2767476 for an attempted fix
        // which fixes issue #1957 but causes #2129
-       vector dv = v_right * -vecs.y + v_up * vecs.z;
+       vector dv = right * -vecs.y + up * vecs.z;
        w_shotorg = ent.origin + ent.view_ofs + dv;
  
        // now move the shotorg forward as much as requested if possible
        if(antilag)
        {
                if(CS(ent).antilag_debug)
-                       tracebox_antilag(ent, w_shotorg, mi, ma, w_shotorg + v_forward * (vecs.x + nudge), MOVE_NORMAL, ent, CS(ent).antilag_debug);
+                       tracebox_antilag(ent, w_shotorg, mi, ma, w_shotorg + forward * (vecs.x + nudge), MOVE_NORMAL, ent, CS(ent).antilag_debug);
                else
-                       tracebox_antilag(ent, w_shotorg, mi, ma, w_shotorg + v_forward * (vecs.x + nudge), MOVE_NORMAL, ent, ANTILAG_LATENCY(ent));
+                       tracebox_antilag(ent, w_shotorg, mi, ma, w_shotorg + forward * (vecs.x + nudge), MOVE_NORMAL, ent, ANTILAG_LATENCY(ent));
        }
        else
-               tracebox(w_shotorg, mi, ma, w_shotorg + v_forward * (vecs.x + nudge), MOVE_NORMAL, ent);
-       w_shotorg = trace_endpos - v_forward * nudge;
+               tracebox(w_shotorg, mi, ma, w_shotorg + forward * (vecs.x + nudge), MOVE_NORMAL, ent);
+       w_shotorg = trace_endpos - forward * nudge;
        // calculate the shotdir from the chosen shotorg
        if(W_DualWielding(ent))
                w_shotdir = s_forward;
@@@ -330,19 -330,25 +330,19 @@@ void fireBullet_trace_callback(vector s
        fireBullet_last_hit = NULL;
  }
  
 -void fireBullet(entity this, .entity weaponentity, vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, entity tracer_effect)
 +void fireBullet_antilag(entity this, .entity weaponentity, vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, entity tracer_effect, bool do_antilag)
  {
 -      vector  end;
 -
        dir = normalize(dir + randomvec() * spread);
 -      end = start + dir * max_shot_distance;
 +      vector end = start + dir * max_shot_distance;
  
        fireBullet_last_hit = NULL;
        fireBullet_trace_callback_eff = tracer_effect;
  
 -      float solid_penetration_left = 1;
 +      float solid_penetration_fraction = 1;
 +      float damage_fraction = 1;
        float total_damage = 0;
  
 -      float lag = ((IS_REAL_CLIENT(this)) ? ANTILAG_LATENCY(this) : 0);
 -      if(lag < 0.001)
 -              lag = 0;
 -      bool noantilag = ((IS_CLIENT(this)) ? CS(this).cvar_cl_noantilag : false);
 -      if(autocvar_g_antilag == 0 || noantilag)
 -              lag = 0; // only do hitscan, but no antilag
 +      float lag = ((do_antilag) ? antilag_getlag(this) : 0);
        if(lag)
                antilag_takeback_all(this, lag);
  
  
        for (;;)
        {
 -              // TODO also show effect while tracing
                WarpZone_TraceBox_ThroughZone(start, '0 0 0', '0 0 0', end, false, WarpZone_trace_forent, NULL, fireBullet_trace_callback);
                dir = WarpZone_TransformVelocity(WarpZone_trace_transform, dir);
                end = WarpZone_TransformOrigin(WarpZone_trace_transform, end);
                        is_weapclip = true;
  
                if(!hit || hit.solid == SOLID_BSP || hit.solid == SOLID_SLIDEBOX)
 -                      Damage_DamageInfo(start, damage * solid_penetration_left, 0, 0, max(1, force) * dir * solid_penetration_left, dtype, hit.species, this);
 +                      Damage_DamageInfo(start, damage * damage_fraction, 0, 0, max(1, force) * dir * damage_fraction, dtype, hit.species, this);
  
                if (hit && hit != WarpZone_trace_forent && hit != fireBullet_last_hit)  // Avoid self-damage (except after going through a warp); avoid hitting the same entity twice (engine bug).
                {
                        MUTATOR_CALLHOOK(FireBullet_Hit, this, hit, start, end, damage, this.(weaponentity));
                        damage = M_ARGV(4, float);
                        bool gooddamage = accuracy_isgooddamage(this, hit);
 -                      Damage(hit, this, this, damage * solid_penetration_left, dtype, weaponentity, start, force * dir * solid_penetration_left);
 +                      Damage(hit, this, this, damage * damage_fraction, dtype, weaponentity, start, force * dir * damage_fraction);
                        // calculate hits for ballistic weapons
                        if(gooddamage)
                        {
                                // do not exceed 100%
 -                              float added_damage = min(damage - total_damage, damage * solid_penetration_left);
 -                              total_damage += damage * solid_penetration_left;
 +                              float added_damage = min(damage - total_damage, damage * damage_fraction);
 +                              total_damage += damage * damage_fraction;
                                accuracy_add(this, this.(weaponentity).m_weapon, 0, added_damage);
                        }
                }
                else if(hitstore.ballistics_density < 0)
                        maxdist = vlen(hit.maxs - hit.mins) + 1; // -1: infinite travel distance
                else if(hitstore.ballistics_density == 0)
 -                      maxdist = max_solid_penetration * solid_penetration_left;
 +                      maxdist = max_solid_penetration * solid_penetration_fraction;
                else
 -                      maxdist = max_solid_penetration * solid_penetration_left * hitstore.ballistics_density;
 +                      maxdist = max_solid_penetration * solid_penetration_fraction / hitstore.ballistics_density;
  
                if(maxdist <= autocvar_g_ballistics_mindistance)
                        break;
                        break;
  
                float dist_taken = max(autocvar_g_ballistics_mindistance, vlen(trace_endpos - start));
 -              // fraction_used_of_what_is_left = dist_taken / maxdist
 -              // solid_penetration_left = solid_penetration_left - solid_penetration_left * fraction_used_of_what_is_left
 -              solid_penetration_left *= 1 - dist_taken / maxdist;
 -              solid_penetration_left = max(solid_penetration_left, 0);
 +              float fraction_used_of_what_is_left = dist_taken / maxdist;
 +              solid_penetration_fraction -= solid_penetration_fraction * fraction_used_of_what_is_left;
 +              solid_penetration_fraction = max(solid_penetration_fraction, 0);
 +              damage_fraction = pow(solid_penetration_fraction, autocvar_g_ballistics_solidpenetration_exponent);
  
                // Only show effect when going through a player (invisible otherwise)
                if (hit && (hit.solid != SOLID_BSP))
                start = trace_endpos;
  
                if(hit.solid == SOLID_BSP)
 -                      Damage_DamageInfo(start, 0, 0, 0, max(1, force) * normalize(dir) * -solid_penetration_left, dtype, 0, this);
 +                      Damage_DamageInfo(start, 0, 0, 0, max(1, force) * normalize(dir) * -damage_fraction, dtype, 0, this);
        }
  
        if(lag)
        if(this)
                this.dphitcontentsmask = oldsolid;
  }
 +
 +void fireBullet(entity this, .entity weaponentity, vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, entity tracer_effect)
 +{
 +      fireBullet_antilag(this, weaponentity, start, dir, spread, max_solid_penetration, damage, force, dtype, tracer_effect, true);
 +}
index d593658a3d2a5bac7b265ebe06331dfa16f508a4,5702c2e3c1bcef94c7b5ecd5ad95c30341dfdb38..6e74738c738eaf5a1bbabcf155bef94c74416ad2
@@@ -163,7 -163,6 +163,7 @@@ void CL_ExteriorWeaponentity_Think(enti
      Weapon wep = this.owner.(weaponentity).m_weapon;
        if (wep) this.glowmod = weaponentity_glowmod(wep, this.owner, this.owner.clientcolors, this.owner.(weaponentity));
        this.colormap = this.owner.colormap;
 +      this.skin = w_ent.skin;
  
        CSQCMODEL_AUTOUPDATE(this);
  }
@@@ -224,7 -223,7 +224,7 @@@ void w_ready(Weapon thiswep, entity act
  .float prevwarntime;
  bool weapon_prepareattack_checkammo(Weapon thiswep, entity actor, bool secondary, .entity weaponentity)
  {
 -      if ((actor.items & IT_UNLIMITED_WEAPON_AMMO)) return true;
 +      if ((actor.items & IT_UNLIMITED_AMMO)) return true;
        bool ammo = false;
        if (secondary) ammo = thiswep.wr_checkammo2(thiswep, actor, weaponentity);
        else ammo = thiswep.wr_checkammo1(thiswep, actor, weaponentity);
@@@ -374,10 -373,6 +374,6 @@@ void weapon_thinkf(entity actor, .entit
                restartanim = fr != WFRAME_IDLE;
        }
  
-       vector of = v_forward;
-       vector or = v_right;
-       vector ou = v_up;
        vector a = '0 0 0';
      this.wframe = fr;
      if (fr == WFRAME_IDLE) a = this.anim_idle;
          a = this.anim_reload;
      a.z *= g_weaponratefactor;
  
-       v_forward = of;
-       v_right = or;
-       v_up = ou;
        if (this.weapon_think == w_ready && func != w_ready && this.state == WS_RAISE) backtrace(
                        "Tried to override initial weapon think function - should this really happen?");
  
@@@ -508,10 -499,8 +500,8 @@@ void W_WeaponFrame(Player actor, .entit
                return;
        }
  
-       makevectors(actor.v_angle);
-       vector fo = v_forward;  // save them in case the weapon think functions change it
-       vector ri = v_right;
-       vector up = v_up;
+       vector fo, ri, up;
+       MAKE_VECTORS(actor.v_angle, fo, ri, up);
  
        // Change weapon
        if (this.m_weapon != this.m_switchweapon)
@@@ -688,7 -677,7 +678,7 @@@ void W_AttachToShotorg(entity actor, .e
  void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use, .entity weaponentity)
  {
        if (MUTATOR_CALLHOOK(W_DecreaseAmmo, actor, actor.(weaponentity), ammo_use)) return;
 -      if ((actor.items & IT_UNLIMITED_WEAPON_AMMO) && !wep.reloading_ammo) return;
 +      if ((actor.items & IT_UNLIMITED_AMMO) && !wep.reloading_ammo) return;
  
        ammo_use = M_ARGV(2, float);
  
@@@ -735,7 -724,7 +725,7 @@@ void W_ReloadedAndReady(Weapon thiswep
        w_ent.clip_load = w_ent.old_clip_load;  // restore the ammo counter, in case we still had ammo in the weapon before reloading
  
        // if the gun uses no ammo, max out weapon load, else decrease ammo as we increase weapon load
 -      if (!w_ent.reload_ammo_min || (actor.items & IT_UNLIMITED_WEAPON_AMMO) || wpn.ammo_type == RES_NONE)
 +      if (!w_ent.reload_ammo_min || (actor.items & IT_UNLIMITED_AMMO) || wpn.ammo_type == RES_NONE)
        {
                w_ent.clip_load = w_ent.reload_ammo_amount;
        }
@@@ -791,7 -780,7 +781,7 @@@ void W_Reload(entity actor, .entity wea
        {
                if (!GetResource(actor, e.ammo_type) && this.reload_ammo_min)
                {
 -                      if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
 +                      if (!(actor.items & IT_UNLIMITED_AMMO))
                        {
                                if (IS_REAL_CLIENT(actor) && actor.reload_complain < time)
                                {
                        }
                }
        }
 -
        if (this)
        {
                if (this.wframe == WFRAME_RELOAD) return;