From 798e27a5ddbc7000f06574e288e9feefb6fa325a Mon Sep 17 00:00:00 2001 From: Samual Date: Tue, 22 May 2012 15:19:57 -0400 Subject: [PATCH] Much more work on the laser prototype... still pretty shitty though, too many things are broken on it/done incorrectly :P --- effectinfo.txt | 51 ++++++++- qcsrc/client/Main.qc | 4 + qcsrc/client/particles.qc | 54 +++++++++ qcsrc/common/constants.qh | 1 + qcsrc/common/util.qc | 192 ++++++++++++++++++++++++++++++++ qcsrc/common/util.qh | 4 + qcsrc/server/cl_weaponsystem.qc | 192 +------------------------------- qcsrc/server/w_laser.qc | 28 ++++- 8 files changed, 330 insertions(+), 196 deletions(-) diff --git a/effectinfo.txt b/effectinfo.txt index 05c249b97..c22bb9c8f 100644 --- a/effectinfo.txt +++ b/effectinfo.txt @@ -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 diff --git a/qcsrc/client/Main.qc b/qcsrc/client/Main.qc index 6072652cd..486696717 100644 --- a/qcsrc/client/Main.qc +++ b/qcsrc/client/Main.qc @@ -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; diff --git a/qcsrc/client/particles.qc b/qcsrc/client/particles.qc index 6e24893b0..3ff3ee9a5 100644 --- a/qcsrc/client/particles.qc +++ b/qcsrc/client/particles.qc @@ -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); +} + diff --git a/qcsrc/common/constants.qh b/qcsrc/common/constants.qh index d0149251f..c22801c19 100644 --- a/qcsrc/common/constants.qh +++ b/qcsrc/common/constants.qh @@ -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; diff --git a/qcsrc/common/util.qc b/qcsrc/common/util.qc index b973850cc..402e4901a 100644 --- a/qcsrc/common/util.qc +++ b/qcsrc/common/util.qc @@ -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 diff --git a/qcsrc/common/util.qh b/qcsrc/common/util.qh index c409de354..e7cb5becc 100644 --- a/qcsrc/common/util.qh +++ b/qcsrc/common/util.qh @@ -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 diff --git a/qcsrc/server/cl_weaponsystem.qc b/qcsrc/server/cl_weaponsystem.qc index 402b692af..d91d7948c 100644 --- a/qcsrc/server/cl_weaponsystem.qc +++ b/qcsrc/server/cl_weaponsystem.qc @@ -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; diff --git a/qcsrc/server/w_laser.qc b/qcsrc/server/w_laser.qc index a05af2fa7..5d9aebe83 100644 --- a/qcsrc/server/w_laser.qc +++ b/qcsrc/server/w_laser.qc @@ -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); } } -- 2.39.2