From a0c96de3cd2b5fd1b57276caafc07e17a54d001a Mon Sep 17 00:00:00 2001
From: Michael Levin <risujin@fastmail.fm>
Date: Sat, 3 Oct 2009 11:17:37 +0000
Subject: Some more work on the Mass Driver: * Fixed a bug in SnapVectorTowards
 which would snap incorrectly if the point was below the world origin. Also
 added an analogous function to work with normals (SnapVectorNormal). * Added
 weapon.cfg to source control to set alwaysImpact (to show flash along with
 blood spurt when hitting a player). * The maximum number of hits allowed
 moved to tremulous.h, set MDRIVER_MAX_HITS. * Since a the visual effects
 changed, removed old massDriverFire() function and toggle switch.

---
 models/weapons/mdriver/weapon.cfg | 13 ++++++
 scripts/weapons.particle          |  6 +--
 src/cgame/cg_weapons.c            | 29 +++++++++----
 src/game/g_weapon.c               | 86 ++++++++++++---------------------------
 src/game/tremulous.h              |  2 +-
 5 files changed, 63 insertions(+), 73 deletions(-)
 create mode 100644 models/weapons/mdriver/weapon.cfg

diff --git a/models/weapons/mdriver/weapon.cfg b/models/weapons/mdriver/weapon.cfg
new file mode 100644
index 00000000..2c74131f
--- /dev/null
+++ b/models/weapons/mdriver/weapon.cfg
@@ -0,0 +1,13 @@
+weaponModel       models/weapons/mdriver/mdriver.md3
+icon              icons/iconw_driver
+crosshair         24 gfx/2d/crosshair-mdriver_s
+
+primary
+{
+  flashDlightColor  0.0 1.0 0.0
+  flashSound        0 models/weapons/mdriver/flash0.wav
+
+  impactMark           6 gfx/marks/bullet_mrk
+  impactParticleSystem models/weapons/mdriver/impactPS
+  alwaysImpact
+}
diff --git a/scripts/weapons.particle b/scripts/weapons.particle
index c0b2ab24..e837c7b0 100644
--- a/scripts/weapons.particle
+++ b/scripts/weapons.particle
@@ -419,11 +419,7 @@ models/weapons/mdriver/impactPS
     {
       shader sync gfx/mdriver/green_particle
       
-      normalDisplacement 1.0
-      
-      velocityType normal
-
-      radius 0 6.0 12.0
+      radius 0 4.0 6.0
       alpha  70 1.0 0.0
       rotation 0 ~360 -
 
diff --git a/src/cgame/cg_weapons.c b/src/cgame/cg_weapons.c
index d5c91aa8..d3c52e13 100644
--- a/src/cgame/cg_weapons.c
+++ b/src/cgame/cg_weapons.c
@@ -1623,18 +1623,33 @@ Draws the mass driver trail
 ==============
 */
 
+#define MDRIVER_MUZZLE_OFFSET 48.0f
+
 void CG_MassDriverFire( entityState_t *es )
 {
+  vec3_t front, frontToBack;
   trailSystem_t *ts;
+  float length;
 
   ts = CG_SpawnNewTrailSystem( cgs.media.massDriverTS );
-  if( CG_IsTrailSystemValid( &ts ) )
-  {
-    CG_SetAttachmentPoint( &ts->frontAttachment, es->origin2 );
-    CG_SetAttachmentPoint( &ts->backAttachment, es->pos.trBase );
-    CG_AttachToPoint( &ts->frontAttachment );
-    CG_AttachToPoint( &ts->backAttachment );
-  }
+  if( !CG_IsTrailSystemValid( &ts ) )
+    return;
+
+  // trail front attaches to the player, needs to be pushed forward a bit
+  // so that it doesn't look like it shot out of the wrong location
+  VectorCopy( es->origin2, front );
+  VectorSubtract( es->pos.trBase, front, frontToBack );
+  length = VectorLength( frontToBack );
+  if( length - MDRIVER_MUZZLE_OFFSET < 0.0f )
+    return;
+  VectorScale( frontToBack, 1.0f / length, frontToBack );
+  VectorMA( front, MDRIVER_MUZZLE_OFFSET, frontToBack, front );
+  CG_SetAttachmentPoint( &ts->frontAttachment, front );
+  CG_AttachToPoint( &ts->frontAttachment );
+
+  // trail back attaches to the impact point
+  CG_SetAttachmentPoint( &ts->backAttachment, es->pos.trBase );
+  CG_AttachToPoint( &ts->backAttachment );
 }
 
 
diff --git a/src/game/g_weapon.c b/src/game/g_weapon.c
index 22d4dd74..52624862 100644
--- a/src/game/g_weapon.c
+++ b/src/game/g_weapon.c
@@ -197,6 +197,7 @@ static void G_WideTrace( trace_t *tr, gentity_t *ent, float range,
 /*
 ======================
 SnapVectorTowards
+SnapVectorNormal
 
 Round a vector to integers for more efficient network
 transmission, but make sure that it rounds towards a given point
@@ -210,10 +211,23 @@ void SnapVectorTowards( vec3_t v, vec3_t to )
 
   for( i = 0 ; i < 3 ; i++ )
   {
-    if( to[ i ] <= v[ i ] )
-      v[ i ] = (int)v[ i ];
+    if( v[ i ] >= 0 )
+      v[ i ] = (int)( v[ i ] + ( to[ i ] <= v[ i ] ? 0 : 1 ) );
     else
-      v[ i ] = (int)v[ i ] + 1;
+      v[ i ] = (int)( v[ i ] + ( to[ i ] <= v[ i ] ? -1 : 0 ) );
+  }
+}
+
+void SnapVectorNormal( vec3_t v, vec3_t normal )
+{
+  int i;
+
+  for( i = 0 ; i < 3 ; i++ )
+  {
+    if( v[ i ] >= 0 )
+      v[ i ] = (int)( v[ i ] + ( normal[ i ] <= 0 ? 0 : 1 ) );
+    else
+      v[ i ] = (int)( v[ i ] + ( normal[ i ] <= 0 ? -1 : 0 ) );
   }
 }
 
@@ -437,14 +451,11 @@ MASS DRIVER
 ======================================================================
 */
 
-#ifdef MDRIVER_SHOOT_THROUGH
-#define MDRIVER_MAX_HITS 16
-
 void massDriverFire( gentity_t *ent )
 {
   trace_t tr;
   vec3_t hitPoints[ MDRIVER_MAX_HITS ], hitNormals[ MDRIVER_MAX_HITS ],
-         origin, originToEnd, muzzleToOrigin, end;
+         origin, originToEnd, muzzleToEnd, muzzleToOrigin, end;
   gentity_t *traceEnts[ MDRIVER_MAX_HITS ], *traceEnt, *tent;
   float length_offset;
   int i, hits = 0, skipent;
@@ -480,17 +491,15 @@ void massDriverFire( gentity_t *ent )
     // save the hit entity, position, and normal
     VectorCopy( tr.endpos, hitPoints[ hits ] );
     VectorCopy( tr.plane.normal, hitNormals[ hits ] );
-    SnapVectorTowards( hitPoints[ hits ], muzzle );
+    SnapVectorNormal( hitPoints[ hits ], tr.plane.normal );
     traceEnts[ hits++ ] = traceEnt;
   }
-  if( !hits )
-    return;
 
   // originate trail line from the gun tip, not the head!  
   VectorCopy( muzzle, origin );
-  VectorMA( origin, -8, up, origin );
-  VectorMA( origin, 6, right, origin );
-  VectorMA( origin, 48, forward, origin );
+  VectorMA( origin, -6, up, origin );
+  VectorMA( origin, 4, right, origin );
+  VectorMA( origin, 24, forward, origin );
   
   // save the final position
   VectorCopy( tr.endpos, end );
@@ -499,7 +508,9 @@ void massDriverFire( gentity_t *ent )
   
   // origin is further in front than muzzle, need to adjust length
   VectorSubtract( origin, muzzle, muzzleToOrigin );
-  length_offset = VectorLength( muzzleToOrigin );
+  VectorSubtract( end, muzzle, muzzleToEnd );
+  VectorNormalize( muzzleToEnd );
+  length_offset = DotProduct( muzzleToEnd, muzzleToOrigin );
 
   // now that the trace is finished, we know where we stopped and can generate
   // visually correct impact locations
@@ -535,7 +546,7 @@ void massDriverFire( gentity_t *ent )
   }
 
   // create an event entity for the trail, doubles as an impact event
-  SnapVectorTowards( end, muzzle );
+  SnapVectorNormal( end, tr.plane.normal );
   tent = G_TempEntity( end, EV_MASS_DRIVER );
   tent->s.eventParm = DirToByte( tr.plane.normal );
   tent->s.weapon = ent->s.weapon;
@@ -545,51 +556,6 @@ void massDriverFire( gentity_t *ent )
   G_UnlaggedOff( );
 }
 
-#else
-
-void massDriverFire( gentity_t *ent )
-{
-  trace_t   tr;
-  vec3_t    end;
-  gentity_t *tent;
-  gentity_t *traceEnt;
-
-  VectorMA( muzzle, 8192 * 16, forward, end );
-
-  G_UnlaggedOn( muzzle, 8192 * 16 );
-  trap_Trace( &tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT );
-  G_UnlaggedOff( );
-
-  if( tr.surfaceFlags & SURF_NOIMPACT )
-    return;
-
-  traceEnt = &g_entities[ tr.entityNum ];
-
-  // snap the endpos to integers, but nudged towards the line
-  SnapVectorTowards( tr.endpos, muzzle );
-
-  // send impact
-  if( traceEnt->takedamage && traceEnt->client )
-  {
-    BloodSpurt( ent, traceEnt, &tr );
-  }
-  else
-  {
-    tent = G_TempEntity( tr.endpos, EV_MISSILE_MISS );
-    tent->s.eventParm = DirToByte( tr.plane.normal );
-    tent->s.weapon = ent->s.weapon;
-    tent->s.generic1 = ent->s.generic1; //weaponMode
-  }
-
-  if( traceEnt->takedamage )
-  {
-    G_Damage( traceEnt, ent, ent, forward, tr.endpos,
-      MDRIVER_DMG, 0, MOD_MDRIVER );
-  }
-}
-
-#endif
-
 /*
 ======================================================================
 
diff --git a/src/game/tremulous.h b/src/game/tremulous.h
index ae56f4a4..55761533 100644
--- a/src/game/tremulous.h
+++ b/src/game/tremulous.h
@@ -422,7 +422,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #define MDRIVER_REPEAT              1000
 #define MDRIVER_K_SCALE             1.0f
 #define MDRIVER_RELOAD              2000
-#define MDRIVER_SHOOT_THROUGH       // uncomment to enable MD shooting through entities
+#define MDRIVER_MAX_HITS            16
 
 #define CHAINGUN_PRICE              400
 #define CHAINGUN_BULLETS            300
-- 
cgit