From 43056dd811051c7810fbe92002af00b314687c73 Mon Sep 17 00:00:00 2001 From: div0 Date: Sun, 28 Feb 2010 19:43:17 +0000 Subject: [PATCH] MinstaNex now can shoot through warpzones... using warpzone-aware tracebox and trailparticles functions Conflicts: data/qcsrc/server/w_crylink.qc git-svn-id: svn://svn.icculus.org/nexuiz/trunk@8698 f962a42d-fe04-0410-a3ab-8c8b0445ebaa --- data/qcsrc/server/cl_weaponsystem.qc | 6 +-- data/qcsrc/server/g_subs.qc | 27 ++++++++++++-- data/qcsrc/server/w_common.qc | 18 +++++---- data/qcsrc/server/w_laser.qc | 2 +- data/qcsrc/server/w_minstanex.qc | 18 ++++----- data/qcsrc/warpzonelib/client.qc | 32 +++++++--------- data/qcsrc/warpzonelib/common.qc | 24 ++++++++++++ data/qcsrc/warpzonelib/common.qh | 4 ++ data/qcsrc/warpzonelib/server.qc | 56 ++++++++++++++++++++++++++++ data/qcsrc/warpzonelib/server.qh | 5 +++ 10 files changed, 150 insertions(+), 42 deletions(-) diff --git a/data/qcsrc/server/cl_weaponsystem.qc b/data/qcsrc/server/cl_weaponsystem.qc index 07ecdb692..8c1b83680 100644 --- a/data/qcsrc/server/cl_weaponsystem.qc +++ b/data/qcsrc/server/cl_weaponsystem.qc @@ -140,12 +140,12 @@ void W_SetupShot_Dir_ProjectileSize(entity ent, vector s_forward, vector mi, vec else ent.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE; if(antilag) - traceline_antilag(world, ent.origin + ent.view_ofs, ent.origin + ent.view_ofs + s_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, ent, ANTILAG_LATENCY(ent)); + WarpZone_traceline_antilag(world, ent.origin + ent.view_ofs, ent.origin + ent.view_ofs + s_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, ent, ANTILAG_LATENCY(ent)); // passing world, because we do NOT want it to touch dphitcontentsmask else - traceline(ent.origin + ent.view_ofs, ent.origin + ent.view_ofs + s_forward * MAX_SHOT_DISTANCE, MOVE_NOMONSTERS, ent); + WarpZone_TraceLine(ent.origin + ent.view_ofs, ent.origin + ent.view_ofs + s_forward * MAX_SHOT_DISTANCE, MOVE_NOMONSTERS, ent); ent.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE; - trueaimpoint = trace_endpos; + trueaimpoint = WarpZone_trace_endpos; // warpzone support // track max damage if not(inWarmupStage) { diff --git a/data/qcsrc/server/g_subs.qc b/data/qcsrc/server/g_subs.qc index a88dc7217..2a7a82d46 100644 --- a/data/qcsrc/server/g_subs.qc +++ b/data/qcsrc/server/g_subs.qc @@ -307,7 +307,7 @@ A version of traceline that must be used by SOLID_SLIDEBOX things that want to h Additionally it moves players back into the past before the trace and restores them afterward. ================== */ -void tracebox_antilag_force (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag) +void tracebox_antilag_force_wz (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag, float wz) { local entity player; local float oldsolid; @@ -337,7 +337,10 @@ void tracebox_antilag_force (entity source, vector v1, vector mi, vector ma, vec } // do the trace - tracebox (v1, mi, ma, v2, nomonst, forent); + if(wz) + WarpZone_TraceBox (v1, mi, ma, v2, nomonst, forent); + else + tracebox (v1, mi, ma, v2, nomonst, forent); // restore players to current positions if (lag) @@ -356,7 +359,7 @@ void tracebox_antilag_force (entity source, vector v1, vector mi, vector ma, vec } void traceline_antilag_force (entity source, vector v1, vector v2, float nomonst, entity forent, float lag) { - tracebox_antilag_force(source, v1, '0 0 0', '0 0 0', v2, nomonst, forent, lag); + tracebox_antilag_force_wz(source, v1, '0 0 0', '0 0 0', v2, nomonst, forent, lag, FALSE); } void traceline_antilag (entity source, vector v1, vector v2, float nomonst, entity forent, float lag) { @@ -368,7 +371,23 @@ void tracebox_antilag (entity source, vector v1, vector mi, vector ma, vector v2 { if (cvar("g_antilag") != 2 || source.cvar_cl_noantilag) lag = 0; - tracebox_antilag_force(source, v1, mi, ma, v2, nomonst, forent, lag); + tracebox_antilag_force_wz(source, v1, mi, ma, v2, nomonst, forent, lag, FALSE); +} +void WarpZone_traceline_antilag_force (entity source, vector v1, vector v2, float nomonst, entity forent, float lag) +{ + tracebox_antilag_force_wz(source, v1, '0 0 0', '0 0 0', v2, nomonst, forent, lag, TRUE); +} +void WarpZone_traceline_antilag (entity source, vector v1, vector v2, float nomonst, entity forent, float lag) +{ + if (cvar("g_antilag") != 2 || source.cvar_cl_noantilag) + lag = 0; + WarpZone_traceline_antilag_force(source, v1, v2, nomonst, forent, lag); +} +void WarpZone_tracebox_antilag (entity source, vector v1, vector mi, vector ma, vector v2, float nomonst, entity forent, float lag) +{ + if (cvar("g_antilag") != 2 || source.cvar_cl_noantilag) + lag = 0; + tracebox_antilag_force_wz(source, v1, mi, ma, v2, nomonst, forent, lag, TRUE); } float tracebox_inverted (vector v1, vector mi, vector ma, vector v2, float nomonsters, entity forent) // returns the number of traces done, for benchmarking diff --git a/data/qcsrc/server/w_common.qc b/data/qcsrc/server/w_common.qc index 0f565ad4c..bca4c8b93 100644 --- a/data/qcsrc/server/w_common.qc +++ b/data/qcsrc/server/w_common.qc @@ -21,6 +21,7 @@ void W_GiveWeapon (entity e, float wep, string name) self = oldself; } +.float railgundistance; void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, float deathtype) { local vector hitloc, force, endpoint, dir; @@ -51,9 +52,9 @@ void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, f while (1) { if(self.antilag_debug) - traceline_antilag (self, start, end, FALSE, self, self.antilag_debug); + WarpZone_traceline_antilag (self, start, end, FALSE, self, self.antilag_debug); else - traceline_antilag (self, start, end, FALSE, self, ANTILAG_LATENCY(self)); + WarpZone_traceline_antilag (self, start, end, FALSE, self, ANTILAG_LATENCY(self)); // if it is world we can't hurt it so stop now if (trace_ent == world || trace_fraction == 1) @@ -63,6 +64,7 @@ void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, f trace_ent.railgunhit = TRUE; trace_ent.railgunhitloc = end; trace_ent.railgunhitsolidbackup = trace_ent.solid; + trace_ent.railgundistance = vlen(WarpZone_trace_endpos - start); // stop if this is a wall if (trace_ent.solid == SOLID_BSP) @@ -117,9 +119,6 @@ void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, f { // get the details we need to call the damage function hitloc = ent.railgunhitloc; - ent.railgunhitloc = '0 0 0'; - ent.railgunhitsolidbackup = SOLID_NOT; - ent.railgunhit = FALSE; //for stats so that team hit will count as a miss if(ent.flags & FL_CLIENT) @@ -130,8 +129,8 @@ void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, f if(ent.team == self.team) hit = 0; - f = ExponentialFalloff(mindist, maxdist, halflifedist, (ent.origin - start) * dir); - ffs = ExponentialFalloff(mindist, maxdist, forcehalflifedist, (ent.origin - start) * dir); + f = ExponentialFalloff(mindist, maxdist, halflifedist, ent.railgundistance); + ffs = ExponentialFalloff(mindist, maxdist, forcehalflifedist, ent.railgundistance); // apply the damage if (ent.takedamage) @@ -141,6 +140,11 @@ void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, f //setorigin (explosion, hitloc); //RadiusDamage (explosion, self, 10, 0, 50, world, 300, deathtype); + ent.railgunhitloc = '0 0 0'; + ent.railgunhitsolidbackup = SOLID_NOT; + ent.railgunhit = FALSE; + ent.railgundistance = 0; + // advance to the next entity ent = findfloat(ent, railgunhit, TRUE); } diff --git a/data/qcsrc/server/w_laser.qc b/data/qcsrc/server/w_laser.qc index a8a097cec..d90c97a38 100644 --- a/data/qcsrc/server/w_laser.qc +++ b/data/qcsrc/server/w_laser.qc @@ -104,7 +104,7 @@ void W_Laser_Attack2 (void) // gauntlet { W_SetupShot (self, TRUE, 0, "weapons/gauntlet_fire.wav", cvar("g_balance_laser_primary_damage")); - traceline_antilag(self, w_shotorg, w_shotorg + w_shotdir * cvar("g_balance_laser_primary_radius"), FALSE, self, ANTILAG_LATENCY(self)); + WarpZone_traceline_antilag(self, w_shotorg, w_shotorg + w_shotdir * cvar("g_balance_laser_primary_radius"), FALSE, self, ANTILAG_LATENCY(self)); pointparticles(particleeffectnum("laser_gauntlet"), w_shotorg + w_shotdir * cvar("g_balance_laser_primary_radius"), '0 0 0', 1); diff --git a/data/qcsrc/server/w_minstanex.qc b/data/qcsrc/server/w_minstanex.qc index 52d099b8f..9240a11f7 100644 --- a/data/qcsrc/server/w_minstanex.qc +++ b/data/qcsrc/server/w_minstanex.qc @@ -47,32 +47,32 @@ void W_MinstaNex_Attack (void) { case COLOR_TEAM1: // Red if(damage_goodhits) - trailparticles(world, particleeffectnum("TE_TEI_G3RED_HIT"), w_shotorg, trace_endpos); + WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3RED_HIT"), w_shotorg, WarpZone_trace_endpos); else - trailparticles(world, particleeffectnum("TE_TEI_G3RED"), w_shotorg, trace_endpos); + WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3RED"), w_shotorg, WarpZone_trace_endpos); break; case COLOR_TEAM2: // Blue if(damage_goodhits) - trailparticles(world, particleeffectnum("TE_TEI_G3BLUE_HIT"), w_shotorg, trace_endpos); + WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3BLUE_HIT"), w_shotorg, WarpZone_trace_endpos); else - trailparticles(world, particleeffectnum("TE_TEI_G3BLUE"), w_shotorg, trace_endpos); + WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3BLUE"), w_shotorg, WarpZone_trace_endpos); break; case COLOR_TEAM3: // Yellow if(damage_goodhits) - trailparticles(world, particleeffectnum("TE_TEI_G3YELLOW_HIT"), w_shotorg, trace_endpos); + WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3YELLOW_HIT"), w_shotorg, WarpZone_trace_endpos); else - trailparticles(world, particleeffectnum("TE_TEI_G3YELLOW"), w_shotorg, trace_endpos); + WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3YELLOW"), w_shotorg, WarpZone_trace_endpos); break; case COLOR_TEAM4: // Pink if(damage_goodhits) - trailparticles(world, particleeffectnum("TE_TEI_G3PINK_HIT"), w_shotorg, trace_endpos); + WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3PINK_HIT"), w_shotorg, WarpZone_trace_endpos); else - trailparticles(world, particleeffectnum("TE_TEI_G3PINK"), w_shotorg, trace_endpos); + WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3PINK"), w_shotorg, WarpZone_trace_endpos); break; } } else - trailparticles(world, particleeffectnum("TE_TEI_G3"), w_shotorg, trace_endpos); + WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3"), w_shotorg, WarpZone_trace_endpos); // flash and burn the wall if (trace_ent.solid == SOLID_BSP && !(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)) diff --git a/data/qcsrc/warpzonelib/client.qc b/data/qcsrc/warpzonelib/client.qc index 664433aa3..987f81f59 100644 --- a/data/qcsrc/warpzonelib/client.qc +++ b/data/qcsrc/warpzonelib/client.qc @@ -6,7 +6,7 @@ void WarpZone_Read(float isnew) self.enemy = spawn(); self.enemy.classname = "warpzone_from"; } - self.classname = "warpzone_to"; + self.classname = "trigger_warpzone"; self.origin_x = ReadCoord(); self.origin_y = ReadCoord(); self.origin_z = ReadCoord(); @@ -53,31 +53,27 @@ void WarpZone_FixView() warpzone_saved_origin = warpzone_fixview_origin; warpzone_saved_angles = warpzone_fixview_angles; - for(e = world; (e = find(e, classname, "warpzone_to")); ) + e = WarpZone_Find(warpzone_fixview_origin, warpzone_fixview_origin); + if(e) { - if(WarpZoneLib_BoxTouchesBrush(warpzone_fixview_origin, warpzone_fixview_origin, e, world)) - { - warpzone_saved = 1; - warpzone_fixview_origin = AnglesTransform_Apply(e.warpzone_transform, warpzone_fixview_origin - e.enemy.oldorigin) + e.oldorigin; - warpzone_fixview_angles = WarpZone_TransformVAngles(e.warpzone_transform, warpzone_fixview_angles); - break; - } + warpzone_saved = 1; + warpzone_fixview_origin = AnglesTransform_Apply(e.warpzone_transform, warpzone_fixview_origin - e.enemy.oldorigin) + e.oldorigin; + warpzone_fixview_angles = WarpZone_TransformVAngles(e.warpzone_transform, warpzone_fixview_angles); + break; } // if we are near any warpzone planes - MOVE AWAY (work around nearclip) float nearclip = 1; - for(e = world; (e = find(e, classname, "warpzone_to")); ) + e = WarpZone_Find(warpzone_fixview_origin - '1 1 1' * nearclip, warpzone_fixview_origin + '1 1 1' * nearclip); + if(e) { - if(WarpZoneLib_BoxTouchesBrush(warpzone_fixview_origin - '1 1 1' * nearclip, warpzone_fixview_origin + '1 1 1' * nearclip, e, world)) + fixedmakevectors(e.enemy.avelocity); + pd = (warpzone_fixview_origin - e.enemy.oldorigin) * v_forward; + if(pd >= 0 && pd < nearclip) { - fixedmakevectors(e.enemy.avelocity); + warpzone_saved = 1; + warpzone_fixview_origin = warpzone_fixview_origin + v_forward * (nearclip - pd); pd = (warpzone_fixview_origin - e.enemy.oldorigin) * v_forward; - if(pd >= 0 && pd < nearclip) - { - warpzone_saved = 1; - warpzone_fixview_origin = warpzone_fixview_origin + v_forward * (nearclip - pd); - pd = (warpzone_fixview_origin - e.enemy.oldorigin) * v_forward; - } } } diff --git a/data/qcsrc/warpzonelib/common.qc b/data/qcsrc/warpzonelib/common.qc index 69c0ca1fd..e5f1be1f7 100644 --- a/data/qcsrc/warpzonelib/common.qc +++ b/data/qcsrc/warpzonelib/common.qc @@ -94,3 +94,27 @@ float WarpZoneLib_BoxTouchesBrush(vector mi, vector ma, entity e, entity ig) return f; } + +entity WarpZone_Find(vector mi, vector ma) +{ + // if we are near any warpzone planes - MOVE AWAY (work around nearclip) + entity e; + for(e = world; (e = find(e, classname, "trigger_warpzone")); ) + if(WarpZoneLib_BoxTouchesBrush(mi, ma, e, world)) + return e; + return world; +} + +void WarpZone_MakeAllSolid() +{ + entity e; + for(e = world; (e = find(e, classname, "trigger_warpzone")); ) + e.solid = SOLID_BSP; +} + +void WarpZone_MakeAllOther() +{ + entity e; + for(e = world; (e = find(e, classname, "trigger_warpzone")); ) + e.solid = SOLID_TRIGGER; +} diff --git a/data/qcsrc/warpzonelib/common.qh b/data/qcsrc/warpzonelib/common.qh index 002e0ee5f..454ac2479 100644 --- a/data/qcsrc/warpzonelib/common.qh +++ b/data/qcsrc/warpzonelib/common.qh @@ -2,3 +2,7 @@ float FL_CAMERA = 8192; vector WarpZone_TransformVAngles(vector t, vector ang); float WarpZoneLib_BoxTouchesBrush(vector mi, vector ma, entity e, entity ig); + +entity WarpZone_Find(vector mi, vector ma); +void WarpZone_MakeAllSolid(); +void WarpZone_MakeAllOther(); diff --git a/data/qcsrc/warpzonelib/server.qc b/data/qcsrc/warpzonelib/server.qc index b084b3198..d3af6d9bd 100644 --- a/data/qcsrc/warpzonelib/server.qc +++ b/data/qcsrc/warpzonelib/server.qc @@ -225,3 +225,59 @@ void WarpZone_InitStep_UpdateTransform() self.flags |= FL_CAMERA; self.view_ofs = self.enemy.warpzone_origin; } + +void WarpZone_TraceBox(vector org, vector mi, vector ma, vector end, float nomonsters, entity forent) +{ + float frac, sol; + vector o0, e0; + o0 = org; + e0 = end; + WarpZone_MakeAllSolid(); + sol = -1; + frac = 0; + for(;;) + { + tracebox(org, mi, ma, end, nomonsters, forent); + if(sol < 0) + sol = trace_startsolid; + if(trace_fraction >= 1) + break; + frac = trace_fraction = frac + (1 - frac) * trace_fraction; + if(trace_ent.classname != "trigger_warpzone") + break; + // we hit a warpzone... so, let's perform the trace after the warp again + org = AnglesTransform_Apply(trace_ent.warpzone_transform, trace_endpos - trace_ent.warpzone_origin) + trace_ent.enemy.warpzone_origin; + end = AnglesTransform_Apply(trace_ent.warpzone_transform, end - trace_ent.warpzone_origin) + trace_ent.enemy.warpzone_origin; + } + WarpZone_MakeAllOther(); + WarpZone_trace_endpos = o0 + (e0 - o0) * trace_fraction; +} + +void WarpZone_TraceLine(vector org, vector end, float nomonsters, entity forent) +{ + WarpZone_TraceBox(org, '0 0 0', '0 0 0', end, nomonsters, forent); +} + +void WarpZone_TrailParticles(entity own, float eff, vector org, vector end) +{ + float frac, sol; + WarpZone_MakeAllSolid(); + sol = -1; + frac = 0; + for(;;) + { + traceline(org, end, MOVE_NOMONSTERS, world); + if(sol < 0) + sol = trace_startsolid; + //print(vtos(org), " to ", vtos(trace_endpos), "\n"); + trailparticles(own, eff, org, trace_endpos); + if(trace_fraction >= 1) + break; + if(trace_ent.classname != "trigger_warpzone") + break; + // we hit a warpzone... so, let's perform the trace after the warp again + org = AnglesTransform_Apply(trace_ent.warpzone_transform, trace_endpos - trace_ent.warpzone_origin) + trace_ent.enemy.warpzone_origin; + end = AnglesTransform_Apply(trace_ent.warpzone_transform, end - trace_ent.warpzone_origin) + trace_ent.enemy.warpzone_origin; + } + WarpZone_MakeAllOther(); +} diff --git a/data/qcsrc/warpzonelib/server.qh b/data/qcsrc/warpzonelib/server.qh index b92296bf5..1c02ab660 100644 --- a/data/qcsrc/warpzonelib/server.qh +++ b/data/qcsrc/warpzonelib/server.qh @@ -8,3 +8,8 @@ void WarpZone_PostTeleportPlayer(entity pl); // server must also define a float called ENT_CLIENT_WARPZONE for the initial byte of WarpZone entities const float ENT_CLIENT_WARPZONE; + +vector WarpZone_trace_endpos; // UNtransformed endpos +void WarpZone_TraceBox(vector org, vector min, vector max, vector end, float nomonsters, entity forent); +void WarpZone_TraceLine(vector org, vector end, float nomonsters, entity forent); +void WarpZone_TrailParticles(entity own, float eff, vector org, vector end); -- 2.39.2