From 73418a947501e6da7e5354aa0cf002318764ba3f Mon Sep 17 00:00:00 2001
From: Michael Levin <risujin@fastmail.fm>
Date: Sat, 3 Oct 2009 11:23:44 +0000
Subject: * Removed unused G_CrushAttack argument Alien wallwalking changes: *
 Can wallwalk on buildables and players * Will cancel when hit with knockback
 from a shove or splash from a weapon * bg_pmove.c has a viewangles
 "correction" removed that would screw up the view when wallwalking on top of
 a player -- I don't know why this "correction" was added, if you find
 wallwalking bugs later this may be the cause Shove function changes: * Will
 shove enemy players (pretty weakly in practice) * Will not shove if you
 aren't trying to move * Can shove wallwalking players (a wallwalking dretch
 could block Tyrants before!)

---
 src/game/bg_pmove.c | 31 ++++--------------
 src/game/g_active.c | 94 +++++++++++++++++++++++++++--------------------------
 src/game/g_local.h  |  2 +-
 src/game/g_weapon.c |  2 +-
 4 files changed, 56 insertions(+), 73 deletions(-)

diff --git a/src/game/bg_pmove.c b/src/game/bg_pmove.c
index 167f40a1..8cad84fe 100644
--- a/src/game/bg_pmove.c
+++ b/src/game/bg_pmove.c
@@ -1833,7 +1833,7 @@ static void PM_GroundClimbTrace( void )
   //used for delta correction
   vec3_t    traceCROSSsurf, traceCROSSref, surfCROSSref;
   float     traceDOTsurf, traceDOTref, surfDOTref, rTtDOTrTsTt;
-  float     traceANGsurf, traceANGref, surfANGref;
+  float     traceANGref, surfANGref;
   vec3_t    horizontal = { 1.0f, 0.0f, 0.0f }; //arbituary vector perpendicular to refNormal
   vec3_t    refTOtrace, refTOsurfTOtrace, tempVec;
   int       rTtANGrTsTt;
@@ -1910,10 +1910,9 @@ static void PM_GroundClimbTrace( void )
         pm->trace( &trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask );
         break;
     }
-
+    
     //if we hit something
-    if( trace.fraction < 1.0f && !( trace.surfaceFlags & ( SURF_SKY | SURF_SLICK ) ) &&
-        !( trace.entityNum != ENTITYNUM_WORLD && i != 4 ) )
+    if( trace.fraction < 1.0f && !( trace.surfaceFlags & ( SURF_SKY | SURF_SLICK ) ) )
     {
       if( i == 2 || i == 3 )
       {
@@ -1935,10 +1934,6 @@ static void PM_GroundClimbTrace( void )
 
       //calculate angle between surf and trace
       traceDOTsurf = DotProduct( trace.plane.normal, surfNormal );
-      traceANGsurf = RAD2DEG( acos( traceDOTsurf ) );
-
-      if( traceANGsurf > 180.0f )
-        traceANGsurf -= 180.0f;
 
       //calculate angle between trace and ref
       traceDOTref = DotProduct( trace.plane.normal, refNormal );
@@ -1970,7 +1965,6 @@ static void PM_GroundClimbTrace( void )
 
           //calculate reference rotated through to surf plane then to trace plane
           RotatePointAroundVector( tempVec, surfCROSSref, horizontal, -surfANGref );
-          RotatePointAroundVector( refTOsurfTOtrace, traceCROSSsurf, tempVec, -traceANGsurf );
 
           //calculate angle between refTOtrace and refTOsurfTOtrace
           rTtDOTrTsTt = DotProduct( refTOtrace, refTOsurfTOtrace );
@@ -1996,10 +1990,6 @@ static void PM_GroundClimbTrace( void )
         //construct a point representing where the player is looking
         VectorAdd( pm->ps->origin, lookdir, point );
 
-        //check whether point is on one side of the plane, if so invert the correction angle
-        if( ( abc[ 0 ] * point[ 0 ] + abc[ 1 ] * point[ 1 ] + abc[ 2 ] * point[ 2 ] - d ) > 0 )
-          traceANGsurf = -traceANGsurf;
-
         //find the . product of the lookdir and traceCROSSsurf
         if( ( ldDOTtCs = DotProduct( lookdir, traceCROSSsurf ) ) < 0.0f )
         {
@@ -2007,15 +1997,6 @@ static void PM_GroundClimbTrace( void )
           ldDOTtCs = DotProduct( lookdir, traceCROSSsurf );
         }
 
-        //set the correction angle
-        traceANGsurf *= 1.0f - ldDOTtCs;
-
-        if( !( pm->ps->persistant[ PERS_STATE ] & PS_WALLCLIMBINGFOLLOW ) )
-        {
-          //correct the angle
-          pm->ps->delta_angles[ PITCH ] -= ANGLE2SHORT( traceANGsurf );
-        }
-
         //transition from wall to ceiling
         //normal for subsequent viewangle rotations
         if( VectorCompare( trace.plane.normal, ceilingNormal ) )
@@ -2048,7 +2029,7 @@ static void PM_GroundClimbTrace( void )
         VectorCopy( trace.plane.normal, pm->ps->grapplePoint );
         pm->ps->stats[ STAT_STATE ] &= ~SS_WALLCLIMBINGCEILING;
       }
-
+      
       //IMPORTANT: break out of the for loop if we've hit something
       break;
     }
@@ -2144,7 +2125,7 @@ static void PM_GroundTrace( void )
         pm->ps->stats[ STAT_STATE ] &= ~SS_WALLCLIMBING;
     }
 
-    if( pm->ps->pm_type == PM_DEAD )
+    if( pm->ps->pm_type == PM_DEAD || pm->ps->pm_time )
       pm->ps->stats[ STAT_STATE ] &= ~SS_WALLCLIMBING;
 
     if( pm->ps->stats[ STAT_STATE ] & SS_WALLCLIMBING )
@@ -2318,7 +2299,7 @@ static void PM_GroundTrace( void )
 
     if( BG_ClassHasAbility( pm->ps->stats[ STAT_PCLASS ], SCA_TAKESFALLDAMAGE ) )
       PM_CrashLand( );
-    }
+  }
 
   pm->ps->groundEntityNum = trace.entityNum;
 
diff --git a/src/game/g_active.c b/src/game/g_active.c
index 56d773ee..090b83d6 100644
--- a/src/game/g_active.c
+++ b/src/game/g_active.c
@@ -191,54 +191,65 @@ void G_SetClientSound( gentity_t *ent )
 
 //==============================================================
 
-static void G_ClientShove( gentity_t *ent, gentity_t *victim )
+/*
+==============
+ClientShove
+==============
+*/
+static int GetClientMass( gentity_t *ent )
 {
-  vec3_t  dir, push;
-  int entMass = 200, vicMass = 200;
+  int entMass = 100;
 
-  // shoving enemies changes gameplay too much
-  if( !OnSameTeam( ent, victim ) )
-    return;
-
-  // alien mass is directly related to their health points
-  // human mass is 200, double for bsuit  
   if( ent->client->pers.teamSelection == PTE_ALIENS )
-  {
     entMass = BG_FindHealthForClass( ent->client->pers.classSelection );
-  }
   else if( ent->client->pers.teamSelection == PTE_HUMANS )
   {
     if( BG_InventoryContainsUpgrade( UP_BATTLESUIT, ent->client->ps.stats ) )
       entMass *= 2;
   }
   else
-    return;
+    return 0;
+  return entMass;
+}
 
-  if( victim->client->pers.teamSelection == PTE_ALIENS )
-  {
-    vicMass = BG_FindHealthForClass( victim->client->pers.classSelection );
-  }
-  else if( BG_InventoryContainsUpgrade( UP_BATTLESUIT,
-    victim->client->ps.stats ) )
-  {
-    vicMass *= 2;
-  }
+static void ClientShove( gentity_t *ent, gentity_t *victim )
+{
+  vec3_t dir, push;
+  float force;
+  int entMass, vicMass;
+  
+  // Don't push if the entity is not trying to move
+  if( !ent->client->pers.cmd.rightmove && !ent->client->pers.cmd.forwardmove &&
+      !ent->client->pers.cmd.upmove )
+    return;
 
+  // Shove is scaled by relative mass
+  entMass = GetClientMass( ent );
+  vicMass = GetClientMass( victim );
   if( vicMass <= 0 || entMass <= 0 )
     return;
 
+  // Give the victim some shove velocity
   VectorSubtract( victim->r.currentOrigin, ent->r.currentOrigin, dir );
   VectorNormalizeFast( dir );
+  force = g_shove.value * entMass / vicMass;
+  VectorScale( dir, force, push );
+  VectorAdd( victim->client->ps.velocity, push, victim->client->ps.velocity );
 
-  // don't break the dretch elevator
-  if( abs( dir[ 2 ] ) > abs( dir[ 0 ] ) && abs( dir[ 2 ] ) > abs( dir[ 1 ] ) )
-    return;
-
-  VectorScale( dir,
-    ( g_shove.value * ( ( float )entMass / ( float )vicMass ) ), push );
-  VectorAdd( victim->client->ps.velocity, push,
-                victim->client->ps.velocity );
-
+  // Set the pmove timer so that the other client can't cancel
+  // out the movement immediately
+  if( !victim->client->ps.pm_time )
+  {
+    int time;
+
+    time = force * 2 + 0.5f;
+    if( time < 50 )
+      time = 50;
+    if( time > 200 )
+      time = 200;
+    victim->client->ps.pm_time = time;
+    victim->client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
+  }
 }
 
 /*
@@ -252,19 +263,11 @@ void ClientImpacts( gentity_t *ent, pmove_t *pm )
   trace_t   trace;
   gentity_t *other;
 
+  // clear a fake trace struct for touch function
   memset( &trace, 0, sizeof( trace ) );
 
   for( i = 0; i < pm->numtouch; i++ )
   {
-    for( j = 0; j < i; j++ )
-    {
-      if( pm->touchents[ j ] == pm->touchents[ i ] )
-        break;
-    }
-
-    if( j != i )
-      continue; // duplicated
-
     other = &g_entities[ pm->touchents[ i ] ];
 
     // see G_UnlaggedDetectCollisions(), this is the inverse of that.
@@ -278,17 +281,16 @@ void ClientImpacts( gentity_t *ent, pmove_t *pm )
     if( ent->client->ps.weapon == WP_ALEVEL4 )
     {
       G_ChargeAttack( ent, other );
-      G_CrushAttack( ent, other,
-                     ( pm->cmd.serverTime - pm->ps->commandTime ) * 0.001f );
+      G_CrushAttack( ent, other );
     }
 
+    // shove players
     if( ent->client && other->client )
-      G_ClientShove( ent, other );
-
-    if( !other->touch )
-      continue;
+      ClientShove( ent, other );
 
-    other->touch( other, ent, &trace );
+    // touch triggers
+    if( other->touch )
+      other->touch( other, ent, &trace );
   }
 }
 
diff --git a/src/game/g_local.h b/src/game/g_local.h
index db97d8a1..a4a5cd26 100644
--- a/src/game/g_local.h
+++ b/src/game/g_local.h
@@ -899,7 +899,7 @@ qboolean  CheckVenomAttack( gentity_t *ent );
 void      CheckGrabAttack( gentity_t *ent );
 qboolean  CheckPounceAttack( gentity_t *ent );
 void      G_ChargeAttack( gentity_t *ent, gentity_t *victim );
-void      G_CrushAttack( gentity_t *ent, gentity_t *victim, float sec );
+void      G_CrushAttack( gentity_t *ent, gentity_t *victim );
 void      G_UpdateZaps( gentity_t *ent );
 
 
diff --git a/src/game/g_weapon.c b/src/game/g_weapon.c
index b8c0b80d..438350cf 100644
--- a/src/game/g_weapon.c
+++ b/src/game/g_weapon.c
@@ -1398,7 +1398,7 @@ G_CrushAttack
 Should only be called if there was an impact between a tyrant and another player
 ===============
 */
-void G_CrushAttack( gentity_t *ent, gentity_t *victim, float sec )
+void G_CrushAttack( gentity_t *ent, gentity_t *victim )
 {
   vec3_t dir;
   float jump;
-- 
cgit