]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/weapons/calculations.qc
Merge branch 'master' into Mario/wepent_experimental
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / weapons / calculations.qc
index 16b507d14eee683e65c13e28a42399efdd48054f..367bab6afb26c5aba16179d96fae28096b765827 100644 (file)
@@ -1,3 +1,5 @@
+#include "calculations.qh"
+
 // =============================
 //  Explosion Force Calculation
 // =============================
@@ -142,109 +144,161 @@ vector findperpendicular(vector v)
        return normalize(cliptoplane(p, v));
 }
 
+#ifdef SVQC
+       int W_GunAlign(entity this, int preferred_align)
+       {
+               if(this.m_gunalign)
+                       return this.m_gunalign; // no adjustment needed
+
+               entity own = this.owner;
+
+               if(preferred_align < 1 || preferred_align > 4)
+                       preferred_align = 3; // default
+
+               for(int j = 4; j > 1; --j) // > 1 as 1 is just center again
+               {
+                       int taken = 0;
+                       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+                       {
+                               .entity weaponentity = weaponentities[slot];
+                               if(own.(weaponentity).m_gunalign == j) // we know it can't be ours thanks to the above check
+                                       taken |= BIT(j);
+                               if(own.(weaponentity).m_gunalign == preferred_align)
+                                       taken |= BIT(preferred_align);
+                       }
+
+                       if(!(taken & BIT(preferred_align)))
+                               return preferred_align; // prefer the recommended
+                       if(!(taken & BIT(j)))
+                               return j; // or fall back if it's not available
+               }
+
+               return preferred_align; // return it anyway
+       }
+#else
+       int W_GunAlign(entity this, int preferred_align)
+       {
+               return this.m_gunalign > 0 ? this.m_gunalign : preferred_align;
+       }
+#endif
+
+#if 0
+int W_GetGunAlignment(entity player)
+{
+       int gunalign = STAT(GUNALIGN, player);
+       if(gunalign < 1 || gunalign > 4)
+               gunalign = 3; // default value
+       --gunalign;
+
+       return gunalign;
+}
+#endif
+
 vector W_CalculateSpread(vector forward, float spread, float spreadfactor, float spreadstyle)
 {
        float sigma;
        vector v1 = '0 0 0', v2;
        float dx, dy, r;
-       float sstyle;
        spread *= spreadfactor; //g_weaponspreadfactor;
        if(spread <= 0)
                return forward;
-       sstyle = spreadstyle; //autocvar_g_projectiles_spread_style;
 
-       if(sstyle == 0)
-       {
-               // this is the baseline for the spread value!
-               // standard deviation: sqrt(2/5)
-               // density function: sqrt(1-r^2)
-               return forward + randomvec() * spread;
-       }
-       else if(sstyle == 1)
-       {
-               // same thing, basically
-               return normalize(forward + cliptoplane(randomvec() * spread, forward));
-       }
-       else if(sstyle == 2)
-       {
-               // circle spread... has at sigma=1 a standard deviation of sqrt(1/2)
-               sigma = spread * 0.89442719099991587855; // match baseline stddev
-               v1 = findperpendicular(forward);
-               v2 = cross(forward, v1);
-               // random point on unit circle
-               dx = random() * 2 * M_PI;
-               dy = sin(dx);
-               dx = cos(dx);
-               // radius in our dist function
-               r = random();
-               r = sqrt(r);
-               return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
-       }
-       else if(sstyle == 3) // gauss 3d
-       {
-               sigma = spread * 0.44721359549996; // match baseline stddev
-               // note: 2D gaussian has sqrt(2) times the stddev of 1D, so this factor is right
-               v1 = forward;
-               v1_x += gsl_ran_gaussian(sigma);
-               v1_y += gsl_ran_gaussian(sigma);
-               v1_z += gsl_ran_gaussian(sigma);
-               return v1;
-       }
-       else if(sstyle == 4) // gauss 2d
+       switch(spreadstyle)
        {
-               sigma = spread * 0.44721359549996; // match baseline stddev
-               // note: 2D gaussian has sqrt(2) times the stddev of 1D, so this factor is right
-               v1_x = gsl_ran_gaussian(sigma);
-               v1_y = gsl_ran_gaussian(sigma);
-               v1_z = gsl_ran_gaussian(sigma);
-               return normalize(forward + cliptoplane(v1, forward));
+               case 0:
+               {
+                       // this is the baseline for the spread value!
+                       // standard deviation: sqrt(2/5)
+                       // density function: sqrt(1-r^2)
+                       return forward + randomvec() * spread;
+               }
+               case 1:
+               {
+                       // same thing, basically
+                       return normalize(forward + cliptoplane(randomvec() * spread, forward));
+               }
+               case 2:
+               {
+                       // circle spread... has at sigma=1 a standard deviation of sqrt(1/2)
+                       sigma = spread * 0.89442719099991587855; // match baseline stddev
+                       v1 = findperpendicular(forward);
+                       v2 = cross(forward, v1);
+                       // random point on unit circle
+                       dx = random() * 2 * M_PI;
+                       dy = sin(dx);
+                       dx = cos(dx);
+                       // radius in our dist function
+                       r = random();
+                       r = sqrt(r);
+                       return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
+               }
+               case 3: // gauss 3d
+               {
+                       sigma = spread * 0.44721359549996; // match baseline stddev
+                       // note: 2D gaussian has sqrt(2) times the stddev of 1D, so this factor is right
+                       v1 = forward;
+                       v1_x += gsl_ran_gaussian(sigma);
+                       v1_y += gsl_ran_gaussian(sigma);
+                       v1_z += gsl_ran_gaussian(sigma);
+                       return v1;
+               }
+               case 4: // gauss 2d
+               {
+                       sigma = spread * 0.44721359549996; // match baseline stddev
+                       // note: 2D gaussian has sqrt(2) times the stddev of 1D, so this factor is right
+                       v1_x = gsl_ran_gaussian(sigma);
+                       v1_y = gsl_ran_gaussian(sigma);
+                       v1_z = gsl_ran_gaussian(sigma);
+                       return normalize(forward + cliptoplane(v1, forward));
+               }
+               case 5: // 1-r
+               {
+                       sigma = spread * 1.154700538379252; // match baseline stddev
+                       v1 = findperpendicular(forward);
+                       v2 = cross(forward, v1);
+                       // random point on unit circle
+                       dx = random() * 2 * M_PI;
+                       dy = sin(dx);
+                       dx = cos(dx);
+                       // radius in our dist function
+                       r = random();
+                       r = solve_cubic_abcd(-2, 3, 0, -r) * '0 1 0';
+                       return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
+               }
+               case 6: // 1-r^2
+               {
+                       sigma = spread * 1.095445115010332; // match baseline stddev
+                       v1 = findperpendicular(forward);
+                       v2 = cross(forward, v1);
+                       // random point on unit circle
+                       dx = random() * 2 * M_PI;
+                       dy = sin(dx);
+                       dx = cos(dx);
+                       // radius in our dist function
+                       r = random();
+                       r = sqrt(1 - r);
+                       r = sqrt(1 - r);
+                       return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
+               }
+               case 7: // (1-r) (2-r)
+               {
+                       sigma = spread * 1.224744871391589; // match baseline stddev
+                       v1 = findperpendicular(forward);
+                       v2 = cross(forward, v1);
+                       // random point on unit circle
+                       dx = random() * 2 * M_PI;
+                       dy = sin(dx);
+                       dx = cos(dx);
+                       // radius in our dist function
+                       r = random();
+                       r = 1 - sqrt(r);
+                       r = 1 - sqrt(r);
+                       return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
+               }
+               default:
+                       error("g_projectiles_spread_style must be 0 (sphere), 1 (flattened sphere), 2 (circle), 3 (gauss 3D), 4 (gauss plane), 5 (linear falloff), 6 (quadratic falloff), 7 (stronger falloff)!");
        }
-       else if(sstyle == 5) // 1-r
-       {
-               sigma = spread * 1.154700538379252; // match baseline stddev
-               v1 = findperpendicular(forward);
-               v2 = cross(forward, v1);
-               // random point on unit circle
-               dx = random() * 2 * M_PI;
-               dy = sin(dx);
-               dx = cos(dx);
-               // radius in our dist function
-               r = random();
-               r = solve_cubic_abcd(-2, 3, 0, -r) * '0 1 0';
-               return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
-       }
-       else if(sstyle == 6) // 1-r^2
-       {
-               sigma = spread * 1.095445115010332; // match baseline stddev
-               v1 = findperpendicular(forward);
-               v2 = cross(forward, v1);
-               // random point on unit circle
-               dx = random() * 2 * M_PI;
-               dy = sin(dx);
-               dx = cos(dx);
-               // radius in our dist function
-               r = random();
-               r = sqrt(1 - r);
-               r = sqrt(1 - r);
-               return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
-       }
-       else if(sstyle == 7) // (1-r) (2-r)
-       {
-               sigma = spread * 1.224744871391589; // match baseline stddev
-               v1 = findperpendicular(forward);
-               v2 = cross(forward, v1);
-               // random point on unit circle
-               dx = random() * 2 * M_PI;
-               dy = sin(dx);
-               dx = cos(dx);
-               // radius in our dist function
-               r = random();
-               r = 1 - sqrt(r);
-               r = 1 - sqrt(r);
-               return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
-       }
-       else
-               error("g_projectiles_spread_style must be 0 (sphere), 1 (flattened sphere), 2 (circle), 3 (gauss 3D), 4 (gauss plane), 5 (linear falloff), 6 (quadratic falloff), 7 (stronger falloff)!");
+
        return '0 0 0';
        /*
         * how to derive falloff functions: