//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
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;
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);
+}
+
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;
}
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
// 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
}
}
-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;
}
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;
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;
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
{
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);
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);
//}
}
}
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);
}
}