]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Much more work on the laser prototype... still pretty shitty though, too many things...
authorSamual <samual@decrux.(none)>
Tue, 22 May 2012 19:19:57 +0000 (15:19 -0400)
committerSamual <samual@decrux.(none)>
Tue, 22 May 2012 19:19:57 +0000 (15:19 -0400)
effectinfo.txt
qcsrc/client/Main.qc
qcsrc/client/particles.qc
qcsrc/common/constants.qh
qcsrc/common/util.qc
qcsrc/common/util.qh
qcsrc/server/cl_weaponsystem.qc
qcsrc/server/w_laser.qc

index 05c249b976d02cb746dbaa95451bd6c6f16fe9ba..c22bb9c8fadc9b373e1bddf0f44d5fda21fb9903 100644 (file)
@@ -7409,4 +7409,53 @@ velocityjitter 64 64 64
 //lightradius 50
 //lightradiusfade 50
 //lightcolor 1 0.9 0.7
-//lightshadow 1
\ No newline at end of file
+//lightshadow 1
+
+// used in qcsrc/server/w_hlac.qc:     pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
+// used in qcsrc/server/w_hlac.qc:     pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
+// used in qcsrc/server/w_laser.qc:    pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
+effect laser_shockwave_attack
+// glow and light
+//countabsolute 1
+//type smoke
+//color 0xcc0000 0xff0000
+//tex 65 65
+//size 10 15
+//alpha 256 512 6280
+//airfriction 10
+//sizeincrease 1.5
+//stretchfactor 2
+//lightradius 200
+//lightradiusfade 2000
+//lightcolor 3 0.1 0.1
+// electricity
+effect laser_shockwave_attack
+count 1
+type spark
+color 0xb44215 0xff0000
+tex 43 43
+size 5 7
+bounce 0
+alpha 4096 4096 20000
+airfriction 1
+originjitter 2 2 2
+velocityjitter 10 10 10
+velocitymultiplier 10
+sizeincrease 1.5
+stretchfactor 2.3
+rotate -180 180 4000 -4000
+// fire
+effect laser_shockwave_attack
+count 1
+type spark
+color 0xff4200 0xff0000
+tex 8 15
+size 7 9
+bounce 0
+alpha 4096 4096 20000
+airfriction 1
+originjitter 2 2 2
+velocityjitter 10 10 10
+velocitymultiplier 10
+sizeincrease 1.5
+stretchfactor 2
index 6072652cd92b845b9d91ddaec16aed26cca39251..48669671753cb7374882ed9530dc53753a571761 100644 (file)
@@ -1185,6 +1185,10 @@ float CSQC_Parse_TempEntity()
                        cl_notice_read();
                        bHandled = true;
                        break;
+               case TE_CSQC_SHOCKWAVEPARTICLE:
+                       Net_ReadShockwaveParticle();
+                       bHandled = true;
+                       break;
                default:
                        // No special logic for this temporary entity; return 0 so the engine can handle it
                        bHandled = false;
index 6e24893b02e005b08d9b3e142dad4d70e6c1efd7..3ff3ee9a5db72f220091df689d54ed514f06fd0f 100644 (file)
@@ -301,3 +301,57 @@ void Net_ReadNexgunBeamParticle()
        else
                WarpZone_TrailParticles_WithMultiplier(world, particleeffectnum("nex_beam"), shotorg, endpos, charge, 1);
 }
+
+void Net_ReadShockwaveParticle()
+{
+       vector shotorg, endpos, deviation;
+       shotorg_x = ReadCoord(); shotorg_y = ReadCoord(); shotorg_z = ReadCoord();
+       endpos_x = ReadCoord(); endpos_y = ReadCoord(); endpos_z = ReadCoord();
+       float spread = ReadByte() / 255.0;
+       
+       float counter, shots;
+
+       shots = 10;
+       
+       vector shotdir = normalize(endpos - shotorg);
+       makevectors(shotdir);
+       vector right = v_right;
+       vector up = v_up;
+       
+       for(counter = 0; counter < shots; ++counter)
+       {
+               deviation = '0 0 0';
+               makevectors('0 360 0' * (0.75 + (counter - 0.5) / (shots - 1)));
+               deviation_y = v_forward_x;
+               deviation_z = v_forward_y;
+               deviation = deviation * spread;
+               //print("v_forward = ", vtos(deviation), ".\n");
+               deviation = ((shotdir + (right * deviation_y) + (up * deviation_z)) * 1000);
+               
+               //deviation = W_CalculateSpread(shotdir, spread, 1, cvar("g_projectiles_spread_style"));
+               //print("deviation = ", vtos(deviation), ".\n");
+               
+               pointparticles(particleeffectnum("laser_shockwave_attack"), shotorg, deviation, 1);
+       }
+       
+       for(counter = 0; counter < shots; ++counter)
+       {
+               //deviation = '0 0 0';
+               //makevectors('0 360 0' * (0.75 + (counter - 0.5) / (shots - 1)));
+               //deviation_y = v_forward_x;
+               //deviation_z = v_forward_y;
+               //deviation = deviation * spread;
+               //print("v_forward = ", vtos(deviation), ".\n");
+               //deviation = ((shotdir + (right * deviation_y) + (up * deviation_z)) * 1000);
+               
+               deviation = W_CalculateSpread(shotdir, spread, 1, cvar("g_projectiles_spread_style"));
+               //print("deviation = ", vtos(deviation), ".\n");
+               
+               pointparticles(particleeffectnum("laser_shockwave_attack"), shotorg, deviation * 1000, 1);
+       }
+       
+       print("definitely doing the effect.\n");
+       
+       //WarpZone_TrailParticles(world, particleeffectnum("nex_beam"), shotorg, endpos);
+}
+
index d0149251f49f6827c80eb06eb33e246ed6b9b069..c22801c1974223fe71a78c3ae29e2da56c6c5243 100644 (file)
@@ -36,6 +36,7 @@ const float TE_CSQC_NEXGUNBEAMPARTICLE = 104;
 const float TE_CSQC_LIGHTNINGARC = 105;
 const float TE_CSQC_TEAMNAGGER = 106;
 const float TE_CSQC_PINGPLREPORT = 107;
+const float TE_CSQC_SHOCKWAVEPARTICLE = 121;
 const float TE_CSQC_ANNOUNCE = 110;
 const float TE_CSQC_TARGET_MUSIC = 111;
 const float TE_CSQC_KILLNOTIFY = 112;
index b973850cc9f23393062a1b60a781e6ead3052d3f..402e4901ad2eb7cabe7ed486ddf042d93c24bbc9 100644 (file)
@@ -2364,3 +2364,195 @@ void queue_to_execute_next_frame(string s)
        }
        to_execute_next_frame = strzone(s);
 }
+
+#ifndef MENUQC
+vector cliptoplane(vector v, vector p)
+{
+       return v - (v * p) * p;
+}
+
+vector solve_cubic_pq(float p, float q)
+{
+       float D, u, v, a;
+       D = q*q/4.0 + p*p*p/27.0;
+       if(D < 0)
+       {
+               // irreducibilis
+               a = 1.0/3.0 * acos(-q/2.0 * sqrt(-27.0/(p*p*p)));
+               u = sqrt(-4.0/3.0 * p);
+               // a in range 0..pi/3
+               // cos(a)
+               // cos(a + 2pi/3)
+               // cos(a + 4pi/3)
+               return
+                       u *
+                       (
+                               '1 0 0' * cos(a + 2.0/3.0*M_PI)
+                               +
+                               '0 1 0' * cos(a + 4.0/3.0*M_PI)
+                               +
+                               '0 0 1' * cos(a)
+                       );
+       }
+       else if(D == 0)
+       {
+               // simple
+               if(p == 0)
+                       return '0 0 0';
+               u = 3*q/p;
+               v = -u/2;
+               if(u >= v)
+                       return '1 1 0' * v + '0 0 1' * u;
+               else
+                       return '0 1 1' * v + '1 0 0' * u;
+       }
+       else
+       {
+               // cardano
+               u = cbrt(-q/2.0 + sqrt(D));
+               v = cbrt(-q/2.0 - sqrt(D));
+               return '1 1 1' * (u + v);
+       }
+}
+vector solve_cubic_abcd(float a, float b, float c, float d)
+{
+       // y = 3*a*x + b
+       // x = (y - b) / 3a
+       float p, q;
+       vector v;
+       p = (9*a*c - 3*b*b);
+       q = (27*a*a*d - 9*a*b*c + 2*b*b*b);
+       v = solve_cubic_pq(p, q);
+       v = (v -  b * '1 1 1') * (1.0 / (3.0 * a));
+       if(a < 0)
+               v += '1 0 -1' * (v_z - v_x); // swap x, z
+       return v;
+}
+
+vector findperpendicular(vector v)
+{
+       vector p;
+       p_x = v_z;
+       p_y = -v_x;
+       p_z = v_y;
+       return normalize(cliptoplane(p, v));
+}
+
+vector W_CalculateSpread(vector forward, float spread, float spreadfactor, float spreadstyle)
+{
+       float sigma;
+       vector v1, 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
+       {
+               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));
+       }
+       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:
+        * rho(r) := (2-r) * (1-r);
+        * a : 0;
+        * b : 1;
+        * rhor(r) := r * rho(r);
+        * cr(t) := integrate(rhor(r), r, a, t);
+        * scr(t) := integrate(rhor(r) * r^2, r, a, t);
+        * variance : scr(b) / cr(b);
+        * solve(cr(r) = rand * cr(b), r), programmmode:false;
+        * sqrt(0.4 / variance), numer;
+        */
+}
+#endif
index c409de3544578c00acc39b6b4e0c2248fabe65f3..e7cb5beccc76552d6cf9237834f77af29c980b38 100644 (file)
@@ -320,3 +320,7 @@ void queue_to_execute_next_frame(string s);
 
 // for marking written-to values as unused where it's a good idea to do this
 noref float unused_float;
+
+#ifndef MENUQC
+vector W_CalculateSpread(vector forward, float spread, float spreadfactor, float spreadstyle)
+#endif
index 402b692af1230fba959a89c1fce3aef5a999ab13..d91d7948ce989f94ee7e779ea48f316b80ed6b94 100644 (file)
@@ -1121,196 +1121,6 @@ void W_AttachToShotorg(entity flash, vector offset)
        }
 }
 
-vector cliptoplane(vector v, vector p)
-{
-       return v - (v * p) * p;
-}
-
-vector solve_cubic_pq(float p, float q)
-{
-       float D, u, v, a;
-       D = q*q/4.0 + p*p*p/27.0;
-       if(D < 0)
-       {
-               // irreducibilis
-               a = 1.0/3.0 * acos(-q/2.0 * sqrt(-27.0/(p*p*p)));
-               u = sqrt(-4.0/3.0 * p);
-               // a in range 0..pi/3
-               // cos(a)
-               // cos(a + 2pi/3)
-               // cos(a + 4pi/3)
-               return
-                       u *
-                       (
-                               '1 0 0' * cos(a + 2.0/3.0*M_PI)
-                               +
-                               '0 1 0' * cos(a + 4.0/3.0*M_PI)
-                               +
-                               '0 0 1' * cos(a)
-                       );
-       }
-       else if(D == 0)
-       {
-               // simple
-               if(p == 0)
-                       return '0 0 0';
-               u = 3*q/p;
-               v = -u/2;
-               if(u >= v)
-                       return '1 1 0' * v + '0 0 1' * u;
-               else
-                       return '0 1 1' * v + '1 0 0' * u;
-       }
-       else
-       {
-               // cardano
-               u = cbrt(-q/2.0 + sqrt(D));
-               v = cbrt(-q/2.0 - sqrt(D));
-               return '1 1 1' * (u + v);
-       }
-}
-vector solve_cubic_abcd(float a, float b, float c, float d)
-{
-       // y = 3*a*x + b
-       // x = (y - b) / 3a
-       float p, q;
-       vector v;
-       p = (9*a*c - 3*b*b);
-       q = (27*a*a*d - 9*a*b*c + 2*b*b*b);
-       v = solve_cubic_pq(p, q);
-       v = (v -  b * '1 1 1') * (1.0 / (3.0 * a));
-       if(a < 0)
-               v += '1 0 -1' * (v_z - v_x); // swap x, z
-       return v;
-}
-
-vector findperpendicular(vector v)
-{
-       vector p;
-       p_x = v_z;
-       p_y = -v_x;
-       p_z = v_y;
-       return normalize(cliptoplane(p, v));
-}
-
-vector W_CalculateProjectileSpread(vector forward, float spread)
-{
-       float sigma;
-       vector v1, v2;
-       float dx, dy, r;
-       float sstyle;
-       spread *= g_weaponspreadfactor;
-       if(spread <= 0)
-               return forward;
-       sstyle = 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
-       {
-               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));
-       }
-       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:
-        * rho(r) := (2-r) * (1-r);
-        * a : 0;
-        * b : 1;
-        * rhor(r) := r * rho(r);
-        * cr(t) := integrate(rhor(r), r, a, t);
-        * scr(t) := integrate(rhor(r) * r^2, r, a, t);
-        * variance : scr(b) / cr(b);
-        * solve(cr(r) = rand * cr(b), r), programmmode:false;
-        * sqrt(0.4 / variance), numer;
-        */
-}
-
 #if 0
 float mspercallsum;
 float mspercallsstyle;
@@ -1334,7 +1144,7 @@ void W_SetupProjectileVelocityEx(entity missile, vector dir, vector upDir, float
        }
        mspercallsum -= gettime(GETTIME_HIRES);
 #endif
-       dir = W_CalculateProjectileSpread(dir, spread);
+       dir = W_CalculateSpread(dir, spread, g_weaponspreadfactor, autocvar_g_projectiles_spread_style);
 #if 0
        mspercallsum += gettime(GETTIME_HIRES);
        mspercallcount += 1;
index a05af2fa72ed12625faf5f0f89568f69a4c46e64..5d9aebe8396ead2b30677f4d479286c71bfb9cc2 100644 (file)
@@ -5,6 +5,20 @@ REGISTER_WEAPON(LASER, w_laser, 0, 1, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WE
 void(float imp) W_SwitchWeapon;
 void() W_LastWeapon;
 
+void SendCSQCShockwaveParticle(float spread, vector endpos) 
+{
+       //WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
+       WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
+       WriteByte(MSG_BROADCAST, TE_CSQC_SHOCKWAVEPARTICLE);
+       WriteCoord(MSG_BROADCAST, w_shotorg_x);
+       WriteCoord(MSG_BROADCAST, w_shotorg_y);
+       WriteCoord(MSG_BROADCAST, w_shotorg_z);
+       WriteCoord(MSG_BROADCAST, endpos_x);
+       WriteCoord(MSG_BROADCAST, endpos_y);
+       WriteCoord(MSG_BROADCAST, endpos_z);
+       WriteByte(MSG_BROADCAST, bound(0, 255 * spread, 255));
+}
+
 void W_Laser_Touch (void)
 {
        PROJECTILE_TOUCH;
@@ -48,7 +62,7 @@ void W_Laser_Shockwave (void)
        if(trace_fraction < 1) // Yes, it is a close range jump
        {
                RadiusDamageForSource(self, trace_endpos, '0 0 0', self, autocvar_g_balance_laser_primary_damage, autocvar_g_balance_laser_primary_edgedamage, autocvar_g_balance_laser_primary_jumpradius, world, TRUE, autocvar_g_balance_laser_primary_force, WEP_LASER, world);
-               pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+               SendCSQCShockwaveParticle(autocvar_g_balance_laser_primary_spread, trace_endpos);
        }
        else // No, it's a mid range attack
        {
@@ -56,7 +70,7 @@ void W_Laser_Shockwave (void)
                targpos = (w_shotorg + (w_shotdir * autocvar_g_balance_laser_primary_radius));
                WarpZone_TraceLine(w_shotorg, targpos, MOVE_WORLDONLY, self);
                
-               te_lightning2(world, trace_endpos, w_shotorg);
+               //te_lightning2(world, trace_endpos, w_shotorg);
                
                attack_endpos = trace_endpos;
                //total_attack_range = vlen(w_shotorg - trace_endpos);
@@ -93,10 +107,15 @@ void W_Laser_Shockwave (void)
                                                        final_force = (normalize(nearest - w_shotorg) * autocvar_g_balance_laser_primary_force);
                                                        final_damage = (autocvar_g_balance_laser_primary_damage * final_damage + autocvar_g_balance_laser_primary_edgedamage * (1 - final_damage));
                                                        
+                                                       print(strcat("damage: ", ftos(final_damage), ", force: ", vtos(final_force), ".\n"));
+                                                       
                                                        Damage(head, self, self, final_damage, WEP_LASER, w_shotorg, final_force);
                                                        
                                                        print(strcat(vtos(angle_to_head), " - ", vtos(angle_to_attack), ": ", ftos(vlen(angle_to_head - angle_to_attack)), ".\n"));
-                                                       te_lightning2(world, nearest, w_shotorg);
+                                                       //te_lightning2(world, nearest, w_shotorg);
+                                                       
+                                                       //pointparticles(particleeffectnum("rocket_guide"), w_shotorg, w_shotdir * 1000, 1);
+                                                       //SendCSQCShockwaveParticle(autocvar_g_balance_laser_primary_spread, trace_endpos);
                                                //}
                                        }
                                }
@@ -104,7 +123,8 @@ void W_Laser_Shockwave (void)
                        
                        head = next;
                }
-               pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+               SendCSQCShockwaveParticle(autocvar_g_balance_laser_primary_spread, trace_endpos);
+               //pointparticles(particleeffectnum("laser_shockwave_attack"), w_shotorg, w_shotdir * 1000, 1);
        }
 }