summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cgame/cg_buildable.c6
-rw-r--r--src/cgame/cg_main.c4
-rw-r--r--src/cgame/cg_players.c21
-rw-r--r--src/game/bg_misc.c551
-rw-r--r--src/game/bg_pmove.c7
-rw-r--r--src/game/bg_public.h36
-rw-r--r--src/game/g_main.c3
-rw-r--r--src/game/g_missile.c9
-rw-r--r--src/game/g_weapon.c7
9 files changed, 616 insertions, 28 deletions
diff --git a/src/cgame/cg_buildable.c b/src/cgame/cg_buildable.c
index 51176488..2715529e 100644
--- a/src/cgame/cg_buildable.c
+++ b/src/cgame/cg_buildable.c
@@ -730,6 +730,9 @@ void CG_GhostBuildable( buildable_t buildable )
CG_CapTrace( &tr, start, mins, maxs, end, ps->clientNum, MASK_PLAYERSOLID );
VectorMA( entity_origin, tr.fraction * -TRACE_DEPTH, tr.plane.normal, ent.origin );
+ //offset on the Z axis if required
+ VectorMA( ent.origin, BG_FindZOffsetForBuildable( buildable ), tr.plane.normal, ent.origin );
+
VectorCopy( ent.origin, ent.lightingOrigin );
VectorCopy( ent.origin, ent.oldorigin ); // don't positionally lerp at all
@@ -942,6 +945,9 @@ void CG_Buildable( centity_t *cent )
VectorMA( ent.origin, tr.fraction * -TRACE_DEPTH, surfNormal, ent.origin );
}
+ //offset on the Z axis if required
+ VectorMA( ent.origin, BG_FindZOffsetForBuildable( es->modelindex ), surfNormal, ent.origin );
+
VectorCopy( ent.origin, ent.oldorigin ); // don't positionally lerp at all
VectorCopy( ent.origin, ent.lightingOrigin );
diff --git a/src/cgame/cg_main.c b/src/cgame/cg_main.c
index 53cecc20..249b86c9 100644
--- a/src/cgame/cg_main.c
+++ b/src/cgame/cg_main.c
@@ -1666,6 +1666,10 @@ void CG_Init( int serverMessageNum, int serverCommandSequence, int clientNum )
//inform UI to repress cursor whilst loading
trap_Cvar_Set( "ui_loading", "1" );
+ //TA: load overrides
+ BG_InitClassOverrides( );
+ BG_InitBuildableOverrides( );
+
//TA: dyn memory
CG_InitMemory( );
diff --git a/src/cgame/cg_players.c b/src/cgame/cg_players.c
index 22db91e1..9dd06cd7 100644
--- a/src/cgame/cg_players.c
+++ b/src/cgame/cg_players.c
@@ -1564,7 +1564,7 @@ Returns the Z component of the surface being shadowed
===============
*/
#define SHADOW_DISTANCE 128
-static qboolean CG_PlayerShadow( centity_t *cent, float *shadowPlane )
+static qboolean CG_PlayerShadow( centity_t *cent, float *shadowPlane, pClass_t class )
{
vec3_t end, mins = { -15, -15, 0 }, maxs = { 15, 15, 2 };
trace_t trace;
@@ -1596,7 +1596,8 @@ static qboolean CG_PlayerShadow( centity_t *cent, float *shadowPlane )
// add the mark as a temporary, so it goes directly to the renderer
// without taking a spot in the cg_marks array
CG_ImpactMark( cgs.media.shadowMarkShader, trace.endpos, trace.plane.normal,
- cent->pe.legs.yawAngle, alpha,alpha,alpha,1, qfalse, 24, qtrue );
+ cent->pe.legs.yawAngle, alpha,alpha,alpha,1, qfalse,
+ 24 * BG_FindShadowScaleForClass( class ), qtrue );
return qtrue;
}
@@ -1836,12 +1837,13 @@ void CG_Player( centity_t *cent )
qboolean shadow;
float shadowPlane;
entityState_t *es = &cent->currentState;
- int class = ( es->powerups >> 8 ) & 0xFF;
+ pClass_t class = ( es->powerups >> 8 ) & 0xFF;
float scale;
vec3_t tempAxis[ 3 ], tempAxis2[ 3 ];
vec3_t angles;
int held = es->modelindex;
pTeam_t team = es->powerups & 0xFF;
+ vec3_t surfNormal = { 0.0f, 0.0f, 1.0f };
// the client number is stored in clientNum. It can't be derived
// from the entity number, because a single client may have
@@ -1911,9 +1913,7 @@ void CG_Player( centity_t *cent )
CG_PlayerSprites( cent );
// add the shadow
- //TA: but only for humans FIXME this is dumb
- /*if( team == PTE_HUMANS )*/
- shadow = CG_PlayerShadow( cent, &shadowPlane );
+ shadow = CG_PlayerShadow( cent, &shadowPlane, class );
// add a water splash if partially in and out of water
CG_PlayerSplash( cent );
@@ -1951,7 +1951,7 @@ void CG_Player( centity_t *cent )
//move the origin closer into the wall with a CapTrace
if( es->eFlags & EF_WALLCLIMB && !( es->eFlags & EF_DEAD ) && !( cg.intermissionStarted ) )
{
- vec3_t surfNormal, start, end, mins, maxs;
+ vec3_t start, end, mins, maxs;
trace_t tr;
if( es->eFlags & EF_WALLCLIMBCEILING )
@@ -1982,6 +1982,11 @@ void CG_Player( centity_t *cent )
legs.nonNormalizedAxes = qtrue;
}
+ //offset on the Z axis if required
+ VectorMA( legs.origin, BG_FindZOffsetForClass( class ), surfNormal, legs.origin );
+ VectorCopy( legs.origin, legs.lightingOrigin );
+ VectorCopy( legs.origin, legs.oldorigin ); // don't positionally lerp at all
+
trap_R_AddRefEntityToScene( &legs );
// if the model failed, allow the default nullmodel to be displayed
@@ -2121,7 +2126,7 @@ void CG_Corpse( centity_t *cent )
}
// add the shadow
- shadow = CG_PlayerShadow( cent, &shadowPlane );
+ shadow = CG_PlayerShadow( cent, &shadowPlane, es->clientNum );
// get the player model information
renderfx = 0;
diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c
index 0478c2c8..643b2433 100644
--- a/src/game/bg_misc.c
+++ b/src/game/bg_misc.c
@@ -28,6 +28,7 @@ buildableAttributes_t bg_buildableList[ ] =
{ "models/buildables/bioegg/bioegg.md3", 0, 0, 0 },
{ -15, -15, -15 }, //vec3_t mins;
{ 15, 15, 15 }, //vec3_t maxs;
+ 0.0f, //float zOffset;
TR_GRAVITY, //trType_t traj;
0.0, //float bounce;
ASPAWN_BP, //int buildPoints;
@@ -61,6 +62,7 @@ buildableAttributes_t bg_buildableList[ ] =
{ "models/buildables/barricade/barricade.md3", 0, 0, 0 },
{ -35, -35, -15 }, //vec3_t mins;
{ 35, 35, 60 }, //vec3_t maxs;
+ 0.0f, //float zOffset;
TR_GRAVITY, //trType_t traj;
0.0, //float bounce;
BARRICADE_BP, //int buildPoints;
@@ -94,6 +96,7 @@ buildableAttributes_t bg_buildableList[ ] =
{ "models/buildables/booster/booster.md3", 0, 0, 0 },
{ -26, -26, -9 }, //vec3_t mins;
{ 26, 26, 9 }, //vec3_t maxs;
+ 0.0f, //float zOffset;
TR_GRAVITY, //trType_t traj;
0.0, //float bounce;
BOOSTER_BP, //int buildPoints;
@@ -125,8 +128,9 @@ buildableAttributes_t bg_buildableList[ ] =
"Acid Tube", //char *humanName;
"team_alien_acid_tube",//char *entityName;
{ "models/buildables/acid_tube/acid_tube.md3", 0, 0, 0 },
- { -35, -35, -11 }, //vec3_t mins;
- { 35, 35, 40 }, //vec3_t maxs;
+ { -25, -25, -25 }, //vec3_t mins;
+ { 25, 25, 25 }, //vec3_t maxs;
+ -15.0f, //float zOffset;
TR_GRAVITY, //trType_t traj;
0.0, //float bounce;
ACIDTUBE_BP, //int buildPoints;
@@ -158,8 +162,9 @@ buildableAttributes_t bg_buildableList[ ] =
"Hive", //char *humanName;
"team_alien_hive", //char *entityName;
{ "models/buildables/acid_tube/acid_tube.md3", 0, 0, 0 },
- { -35, -35, -11 }, //vec3_t mins;
- { 35, 35, 40 }, //vec3_t maxs;
+ { -35, -35, -25 }, //vec3_t mins;
+ { 35, 35, 25 }, //vec3_t maxs;
+ -15.0f, //float zOffset;
TR_GRAVITY, //trType_t traj;
0.0, //float bounce;
HIVE_BP, //int buildPoints;
@@ -193,6 +198,7 @@ buildableAttributes_t bg_buildableList[ ] =
{ "models/buildables/trapper/trapper.md3", 0, 0, 0 },
{ -15, -15, -15 }, //vec3_t mins;
{ 15, 15, 15 }, //vec3_t maxs;
+ 0.0f, //float zOffset;
TR_GRAVITY, //trType_t traj;
0.0, //float bounce;
TRAPPER_BP, //int buildPoints;
@@ -226,6 +232,7 @@ buildableAttributes_t bg_buildableList[ ] =
{ "models/buildables/hivemind/hivemind.md3", 0, 0, 0 },
{ -45, -45, -15 }, //vec3_t mins;
{ 45, 45, 95 }, //vec3_t maxs;
+ 0.0f, //float zOffset;
TR_GRAVITY, //trType_t traj;
0.0, //float bounce;
OVERMIND_BP, //int buildPoints;
@@ -259,6 +266,7 @@ buildableAttributes_t bg_buildableList[ ] =
{ "models/buildables/hovel/hovel.md3", 0, 0, 0 },
{ -50, -50, -20 }, //vec3_t mins;
{ 50, 50, 20 }, //vec3_t maxs;
+ 0.0f, //float zOffset;
TR_GRAVITY, //trType_t traj;
0.0, //float bounce;
HOVEL_BP, //int buildPoints;
@@ -292,6 +300,7 @@ buildableAttributes_t bg_buildableList[ ] =
{ "models/buildables/replicator/replicator.md3", 0, 0, 0 },
{ -40, -40, -4 }, //vec3_t mins;
{ 40, 40, 4 }, //vec3_t maxs;
+ 0.0f, //float zOffset;
TR_GRAVITY, //trType_t traj;
0.0, //float bounce;
HSPAWN_BP, //int buildPoints;
@@ -325,6 +334,7 @@ buildableAttributes_t bg_buildableList[ ] =
{ "models/buildables/medistat/medistat.md3", 0, 0, 0 },
{ -35, -35, -7 }, //vec3_t mins;
{ 35, 35, 7 }, //vec3_t maxs;
+ 0.0f, //float zOffset;
TR_GRAVITY, //trType_t traj;
0.0, //float bounce;
MEDISTAT_BP, //int buildPoints;
@@ -360,6 +370,7 @@ buildableAttributes_t bg_buildableList[ ] =
"models/buildables/mgturret/turret_top.md3", 0 },
{ -25, -25, -20 }, //vec3_t mins;
{ 25, 25, 20 }, //vec3_t maxs;
+ 0.0f, //float zOffset;
TR_GRAVITY, //trType_t traj;
0.0, //float bounce;
MGTURRET_BP, //int buildPoints;
@@ -393,6 +404,7 @@ buildableAttributes_t bg_buildableList[ ] =
{ "models/buildables/tesla/tesla.md3", 0, 0, 0 },
{ -22, -22, -40 }, //vec3_t mins;
{ 22, 22, 40 }, //vec3_t maxs;
+ 0.0f, //float zOffset;
TR_GRAVITY, //trType_t traj;
0.0, //float bounce;
TESLAGEN_BP, //int buildPoints;
@@ -426,6 +438,7 @@ buildableAttributes_t bg_buildableList[ ] =
{ "models/buildables/dcc/dcc.md3", 0, 0, 0 },
{ -35, -35, -13 }, //vec3_t mins;
{ 35, 35, 47 }, //vec3_t maxs;
+ 0.0f, //float zOffset;
TR_GRAVITY, //trType_t traj;
0.0, //float bounce;
DC_BP, //int buildPoints;
@@ -459,6 +472,7 @@ buildableAttributes_t bg_buildableList[ ] =
{ "models/buildables/mcu/mcu.md3", 0, 0, 0 },
{ -40, -40, -13 }, //vec3_t mins;
{ 40, 40, 50 }, //vec3_t maxs;
+ 0.0f, //float zOffset;
TR_GRAVITY, //trType_t traj;
0.0, //float bounce;
ARMOURY_BP, //int buildPoints;
@@ -492,6 +506,7 @@ buildableAttributes_t bg_buildableList[ ] =
{ "models/buildables/reactor/reactor.md3", 0, 0, 0 },
{ -50, -50, -15 }, //vec3_t mins;
{ 50, 50, 95 }, //vec3_t maxs;
+ 0.0f, //float zOffset;
TR_GRAVITY, //trType_t traj;
0.0, //float bounce;
REACTOR_BP, //int buildPoints;
@@ -525,6 +540,7 @@ buildableAttributes_t bg_buildableList[ ] =
{ "models/buildables/repeater/repeater.md3", 0, 0, 0 },
{ -15, -15, -15 }, //vec3_t mins;
{ 15, 15, 25 }, //vec3_t maxs;
+ 0.0f, //float zOffset;
TR_GRAVITY, //trType_t traj;
0.0, //float bounce;
REPEATER_BP, //int buildPoints;
@@ -554,6 +570,9 @@ buildableAttributes_t bg_buildableList[ ] =
int bg_numBuildables = sizeof( bg_buildableList ) / sizeof( bg_buildableList[ 0 ] );
+//separate from bg_buildableList to work around char struct init bug
+buildableAttributeOverrides_t bg_buildableOverrideList[ BA_NUM_BUILDABLES ];
+
/*
==============
BG_FindBuildNumForName
@@ -700,6 +719,26 @@ void BG_FindBBoxForBuildable( int bclass, vec3_t mins, vec3_t maxs )
/*
==============
+BG_FindZOffsetForBuildable
+==============
+*/
+float BG_FindZOffsetForBuildable( int bclass )
+{
+ int i;
+
+ for( i = 0; i < bg_numBuildables; i++ )
+ {
+ if( bg_buildableList[ i ].buildNum == bclass )
+ {
+ return bg_buildableList[ i ].zOffset;
+ }
+ }
+
+ return 0.0f;
+}
+
+/*
+==============
BG_FindTrajectoryForBuildable
==============
*/
@@ -1181,6 +1220,156 @@ int BG_FindUniqueTestForBuildable( int bclass )
return qfalse;
}
+/*
+==============
+BG_FindOverrideForBuildable
+==============
+*/
+static buildableAttributeOverrides_t *BG_FindOverrideForBuildable( int bclass )
+{
+ return &bg_buildableOverrideList[ bclass ];
+}
+
+/*
+======================
+BG_ParseBuildableFile
+
+Parses a configuration file describing a builable
+======================
+*/
+static qboolean BG_ParseBuildableFile( const char *filename, buildableAttributeOverrides_t *bao )
+{
+ char *text_p;
+ int i;
+ int len;
+ char *token;
+ char text[ 20000 ];
+ fileHandle_t f;
+ float scale = 0.0f;
+
+
+ // load the file
+ len = trap_FS_FOpenFile( filename, &f, FS_READ );
+ if( len <= 0 )
+ return qfalse;
+
+ if( len >= sizeof( text ) - 1 )
+ {
+ Com_Printf( S_COLOR_RED "ERROR: Buildable file %s too long\n", filename );
+ return qfalse;
+ }
+
+ trap_FS_Read( text, len, f );
+ text[ len ] = 0;
+ trap_FS_FCloseFile( f );
+
+ // parse the text
+ text_p = text;
+
+ // read optional parameters
+ while( 1 )
+ {
+ token = COM_Parse( &text_p );
+
+ if( !token )
+ break;
+
+ if( !Q_stricmp( token, "" ) )
+ break;
+
+ if( !Q_stricmp( token, "model" ) )
+ {
+ int index = 0;
+
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ index = atoi( token );
+
+ if( index < 0 )
+ index = 0;
+ else if( index > 3 )
+ index = 3;
+
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ Q_strncpyz( bao->models[ index ], token, sizeof( bao->models[ 0 ] ) );
+
+ continue;
+ }
+ else if( !Q_stricmp( token, "mins" ) )
+ {
+ for( i = 0; i <= 2; i++ )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ bao->mins[ i ] = atof( token );
+ }
+
+ continue;
+ }
+ else if( !Q_stricmp( token, "maxs" ) )
+ {
+ for( i = 0; i <= 2; i++ )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ bao->maxs[ i ] = atof( token );
+ }
+
+ continue;
+ }
+ else if( !Q_stricmp( token, "zOffset" ) )
+ {
+ float offset;
+
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ offset = atof( token );
+ offset = 0.0f;
+
+ bao->zOffset = offset;
+
+ continue;
+ }
+
+
+ Com_Printf( S_COLOR_RED "ERROR: unknown token '%s'\n", token );
+ return qfalse;
+ }
+
+ return qtrue;
+}
+
+/*
+===============
+BG_InitBuildableOverrides
+
+Set any overrides specfied by file
+===============
+*/
+void BG_InitBuildableOverrides( void )
+{
+ int i;
+ buildableAttributeOverrides_t *bao;
+
+ for( i = BA_NONE + 1; i < BA_NUM_BUILDABLES; i++ )
+ {
+ bao = BG_FindOverrideForBuildable( i );
+
+ BG_ParseBuildableFile( va( "overrides/buildables/%s.cfg", BG_FindNameForBuildable( i ) ), bao );
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
classAttributes_t bg_classList[ ] =
@@ -1192,6 +1381,7 @@ classAttributes_t bg_classList[ ] =
"", //char *modelname;
1.0f, //float modelScale;
"", //char *skinname;
+ 1.0f, //float shadowScale;
"", //char *hudname;
( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
{ -15, -15, -15 }, //vec3_t mins;
@@ -1199,6 +1389,7 @@ classAttributes_t bg_classList[ ] =
{ 15, 15, 15 }, //vec3_t crouchmaxs;
{ -15, -15, -15 }, //vec3_t deadmins;
{ 15, 15, 15 }, //vec3_t deadmaxs;
+ 0.0f, //float zOffset
0, 0, //int viewheight, crouchviewheight;
0, //int health;
0.0f, //float fallDamage;
@@ -1226,6 +1417,7 @@ classAttributes_t bg_classList[ ] =
"builder", //char *modelname;
1.0f, //float modelScale;
"default", //char *skinname;
+ 1.0f, //float shadowScale;
"alien_builder_hud", //char *hudname;
( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
{ -15, -15, -20 }, //vec3_t mins;
@@ -1233,6 +1425,7 @@ classAttributes_t bg_classList[ ] =
{ 15, 15, 20 }, //vec3_t crouchmaxs;
{ -15, -15, -4 }, //vec3_t deadmins;
{ 15, 15, 4 }, //vec3_t deadmaxs;
+ 0.0f, //float zOffset
0, 0, //int viewheight, crouchviewheight;
ABUILDER_HEALTH, //int health;
0.2f, //float fallDamage;
@@ -1261,6 +1454,7 @@ classAttributes_t bg_classList[ ] =
"builder", //char *modelname;
1.0f, //float modelScale;
"advanced", //char *skinname;
+ 1.0f, //float shadowScale;
"alien_builder_hud", //char *hudname;
( 1 << S2 )|( 1 << S3 ), //int stages
{ -20, -20, -20 }, //vec3_t mins;
@@ -1268,6 +1462,7 @@ classAttributes_t bg_classList[ ] =
{ 20, 20, 20 }, //vec3_t crouchmaxs;
{ -20, -20, -4 }, //vec3_t deadmins;
{ 20, 20, 4 }, //vec3_t deadmaxs;
+ 0.0f, //float zOffset
0, 0, //int viewheight, crouchviewheight;
ABUILDER_UPG_HEALTH, //int health;
0.0f, //float fallDamage;
@@ -1296,6 +1491,7 @@ classAttributes_t bg_classList[ ] =
"jumper", //char *modelname;
0.2f, //float modelScale;
"default", //char *skinname;
+ 0.3f, //float shadowScale;
"alien_general_hud", //char *hudname;
( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
{ -15, -15, -15 }, //vec3_t mins;
@@ -1303,6 +1499,7 @@ classAttributes_t bg_classList[ ] =
{ 15, 15, 15 }, //vec3_t crouchmaxs;
{ -15, -15, -4 }, //vec3_t deadmins;
{ 15, 15, 4 }, //vec3_t deadmaxs;
+ -8.0f, //float zOffset
0, 0, //int viewheight, crouchviewheight;
SOLDIER_HEALTH, //int health;
0.0f, //float fallDamage;
@@ -1331,6 +1528,7 @@ classAttributes_t bg_classList[ ] =
"spitter", //char *modelname;
0.6f, //float modelScale;
"default", //char *skinname;
+ 1.0f, //float shadowScale;
"alien_general_hud", //char *hudname;
( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
{ -18, -18, -18 }, //vec3_t mins;
@@ -1338,7 +1536,8 @@ classAttributes_t bg_classList[ ] =
{ 18, 18, 18 }, //vec3_t crouchmaxs;
{ -18, -18, -4 }, //vec3_t deadmins;
{ 18, 18, 4 }, //vec3_t deadmaxs;
- 9, 9, //int viewheight, crouchviewheight;
+ 0.0f, //float zOffset
+ 0, 0, //int viewheight, crouchviewheight;
HYDRA_HEALTH, //int health;
0.0f, //float fallDamage;
HYDRA_REGEN, //int regenRate;
@@ -1367,6 +1566,7 @@ classAttributes_t bg_classList[ ] =
"spitter", //char *modelname;
0.7f, //float modelScale;
"blue", //char *skinname;
+ 1.0f, //float shadowScale;
"alien_general_hud", //char *hudname;
( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
{ -20, -20, -20 }, //vec3_t mins;
@@ -1374,7 +1574,8 @@ classAttributes_t bg_classList[ ] =
{ 20, 20, 20 }, //vec3_t crouchmaxs;
{ -20, -20, -4 }, //vec3_t deadmins;
{ 20, 20, 4 }, //vec3_t deadmaxs;
- 10, 10, //int viewheight, crouchviewheight;
+ 0.0f, //float zOffset
+ 0, 0, //int viewheight, crouchviewheight;
HYDRA_UPG_HEALTH, //int health;
0.0f, //float fallDamage;
HYDRA_UPG_REGEN, //int regenRate;
@@ -1403,6 +1604,7 @@ classAttributes_t bg_classList[ ] =
"tarantula", //char *modelname;
0.75f, //float modelScale;
"default", //char *skinname;
+ 1.0f, //float shadowScale;
"alien_general_hud", //char *hudname;
( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
{ -22, -22, -22 }, //vec3_t mins;
@@ -1410,6 +1612,7 @@ classAttributes_t bg_classList[ ] =
{ 22, 22, 22 }, //vec3_t crouchmaxs;
{ -22, -22, -4 }, //vec3_t deadmins;
{ 22, 22, 4 }, //vec3_t deadmaxs;
+ 0.0f, //float zOffset
10, 10, //int viewheight, crouchviewheight;
CHIMERA_HEALTH, //int health;
0.0f, //float fallDamage;
@@ -1438,6 +1641,7 @@ classAttributes_t bg_classList[ ] =
"tarantula", //char *modelname;
0.9f, //float modelScale;
"red", //char *skinname;
+ 1.0f, //float shadowScale;
"alien_general_hud", //char *hudname;
( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
{ -24, -24, -24 }, //vec3_t mins;
@@ -1445,6 +1649,7 @@ classAttributes_t bg_classList[ ] =
{ 24, 24, 24 }, //vec3_t crouchmaxs;
{ -24, -24, -4 }, //vec3_t deadmins;
{ 24, 24, 4 }, //vec3_t deadmaxs;
+ 0.0f, //float zOffset
12, 12, //int viewheight, crouchviewheight;
CHIMERA_UPG_HEALTH, //int health;
0.0f, //float fallDamage;
@@ -1473,6 +1678,7 @@ classAttributes_t bg_classList[ ] =
"prowl", //char *modelname;
1.0f, //float modelScale;
"default", //char *skinname;
+ 1.0f, //float shadowScale;
"alien_general_hud", //char *hudname;
( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
{ -32, -32, -21 }, //vec3_t mins;
@@ -1480,6 +1686,7 @@ classAttributes_t bg_classList[ ] =
{ 32, 32, 21 }, //vec3_t crouchmaxs;
{ -32, -32, -4 }, //vec3_t deadmins;
{ 32, 32, 4 }, //vec3_t deadmaxs;
+ 0.0f, //float zOffset
24, 24, //int viewheight, crouchviewheight;
DRAGOON_HEALTH, //int health;
0.0f, //float fallDamage;
@@ -1508,6 +1715,7 @@ classAttributes_t bg_classList[ ] =
"prowl", //char *modelname;
1.0f, //float modelScale;
"default", //char *skinname;
+ 1.0f, //float shadowScale;
"alien_general_hud", //char *hudname;
( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
{ -32, -32, -21 }, //vec3_t mins;
@@ -1515,6 +1723,7 @@ classAttributes_t bg_classList[ ] =
{ 32, 32, 21 }, //vec3_t crouchmaxs;
{ -32, -32, -4 }, //vec3_t deadmins;
{ 32, 32, 4 }, //vec3_t deadmaxs;
+ 0.0f, //float zOffset
27, 27, //int viewheight, crouchviewheight;
DRAGOON_UPG_HEALTH, //int health;
0.0f, //float fallDamage;
@@ -1543,6 +1752,7 @@ classAttributes_t bg_classList[ ] =
"mofo", //char *modelname;
1.0f, //float modelScale;
"default", //char *skinname;
+ 2.0f, //float shadowScale;
"alien_general_hud", //char *hudname;
( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
{ -30, -30, -20 }, //vec3_t mins;
@@ -1550,6 +1760,7 @@ classAttributes_t bg_classList[ ] =
{ 30, 30, 20 }, //vec3_t crouchmaxs;
{ -15, -15, -4 }, //vec3_t deadmins;
{ 15, 15, 4 }, //vec3_t deadmaxs;
+ 0.0f, //float zOffset
50, 50, //int viewheight, crouchviewheight;
BMOFO_HEALTH, //int health;
0.0f, //float fallDamage;
@@ -1579,6 +1790,7 @@ classAttributes_t bg_classList[ ] =
"sarge", //char *modelname;
1.0f, //float modelScale;
"default", //char *skinname;
+ 1.0f, //float shadowScale;
"human_hud", //char *hudname;
( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int stages
{ -15, -15, -24 }, //vec3_t mins;
@@ -1586,6 +1798,7 @@ classAttributes_t bg_classList[ ] =
{ 15, 15, 16 }, //vec3_t crouchmaxs;
{ -15, -15, -4 }, //vec3_t deadmins;
{ 15, 15, 4 }, //vec3_t deadmaxs;
+ 0.0f, //float zOffset
26, 12, //int viewheight, crouchviewheight;
100, //int health;
1.0f, //float fallDamage;
@@ -1616,15 +1829,19 @@ classAttributes_t bg_classList[ ] =
"keel",
1.0f,
"default",
+ 1.0f,
"bsuit", ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), { 0, 0, 0 }, { 0, 0, 0, },
- { 0, 0, 0, }, { 0, 0, 0, }, { 0, 0, 0, }, 0, 0, 0, 0.0f, 0, 0, WP_NONE, 0.0f, 0,
+ { 0, 0, 0, }, { 0, 0, 0, }, { 0, 0, 0, }, 0.0f, 0, 0, 0, 0.0f, 0, 0, WP_NONE, 0.0f, 0,
0.0f, 1.0f, 0, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 270.0f, { PCL_NONE, PCL_NONE, PCL_NONE }, 0, 0
}
};
int bg_numPclasses = sizeof( bg_classList ) / sizeof( bg_classList[ 0 ] );
+//separate from bg_classList to work around char struct init bug
+classAttributeOverrides_t bg_classOverrideList[ PCL_NUM_CLASSES ];
+
/*
==============
BG_FindClassNumForName
@@ -1693,6 +1910,9 @@ char *BG_FindModelNameForClass( int pclass )
{
int i;
+ if( bg_classOverrideList[ pclass ].modelName[ 0 ] != 0 )
+ return bg_classOverrideList[ pclass ].modelName;
+
for( i = 0; i < bg_numPclasses; i++ )
{
if( bg_classList[ i ].classNum == pclass )
@@ -1713,6 +1933,9 @@ float BG_FindModelScaleForClass( int pclass )
{
int i;
+ if( bg_classOverrideList[ pclass ].modelScale != 0.0f )
+ return bg_classOverrideList[ pclass ].modelScale;
+
for( i = 0; i < bg_numPclasses; i++ )
{
if( bg_classList[ i ].classNum == pclass )
@@ -1734,6 +1957,9 @@ char *BG_FindSkinNameForClass( int pclass )
{
int i;
+ if( bg_classOverrideList[ pclass ].skinName[ 0 ] != 0 )
+ return bg_classOverrideList[ pclass ].skinName;
+
for( i = 0; i < bg_numPclasses; i++ )
{
if( bg_classList[ i ].classNum == pclass )
@@ -1747,6 +1973,30 @@ char *BG_FindSkinNameForClass( int pclass )
/*
==============
+BG_FindShadowScaleForClass
+==============
+*/
+float BG_FindShadowScaleForClass( int pclass )
+{
+ int i;
+
+ if( bg_classOverrideList[ pclass ].shadowScale != 0.0f )
+ return bg_classOverrideList[ pclass ].shadowScale;
+
+ for( i = 0; i < bg_numPclasses; i++ )
+ {
+ if( bg_classList[ i ].classNum == pclass )
+ {
+ return bg_classList[ i ].shadowScale;
+ }
+ }
+
+ Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindShadowScaleForClass( %d )\n", pclass );
+ return 1.0f;
+}
+
+/*
+==============
BG_FindHudNameForClass
==============
*/
@@ -1754,6 +2004,9 @@ char *BG_FindHudNameForClass( int pclass )
{
int i;
+ if( bg_classOverrideList[ pclass ].hudName[ 0 ] != 0 )
+ return bg_classOverrideList[ pclass ].hudName;
+
for( i = 0; i < bg_numPclasses; i++ )
{
if( bg_classList[ i ].classNum == pclass )
@@ -1803,19 +2056,44 @@ void BG_FindBBoxForClass( int pclass, vec3_t mins, vec3_t maxs, vec3_t cmaxs, ve
if( bg_classList[ i ].classNum == pclass )
{
if( mins != NULL )
- VectorCopy( bg_classList[ i ].mins, mins );
+ {
+ VectorCopy( bg_classList[ i ].mins, mins );
+
+ if( VectorLength( bg_classOverrideList[ pclass ].mins ) )
+ VectorCopy( bg_classOverrideList[ pclass ].mins, mins );
+ }
if( maxs != NULL )
- VectorCopy( bg_classList[ i ].maxs, maxs );
+ {
+ VectorCopy( bg_classList[ i ].maxs, maxs );
+
+ if( VectorLength( bg_classOverrideList[ pclass ].maxs ) )
+ VectorCopy( bg_classOverrideList[ pclass ].maxs, maxs );
+ }
if( cmaxs != NULL )
- VectorCopy( bg_classList[ i ].crouchMaxs, cmaxs );
+ {
+ VectorCopy( bg_classList[ i ].crouchMaxs, cmaxs );
+
+ if( VectorLength( bg_classOverrideList[ pclass ].crouchMaxs ) )
+ VectorCopy( bg_classOverrideList[ pclass ].crouchMaxs, cmaxs );
+ }
if( dmins != NULL )
- VectorCopy( bg_classList[ i ].deadMins, dmins );
+ {
+ VectorCopy( bg_classList[ i ].deadMins, dmins );
+
+ if( VectorLength( bg_classOverrideList[ pclass ].deadMins ) )
+ VectorCopy( bg_classOverrideList[ pclass ].deadMins, dmins );
+ }
if( dmaxs != NULL )
- VectorCopy( bg_classList[ i ].deadMaxs, dmaxs );
+ {
+ VectorCopy( bg_classList[ i ].deadMaxs, dmaxs );
+
+ if( VectorLength( bg_classOverrideList[ pclass ].deadMaxs ) )
+ VectorCopy( bg_classOverrideList[ pclass ].deadMaxs, dmaxs );
+ }
return;
}
@@ -1839,6 +2117,30 @@ void BG_FindBBoxForClass( int pclass, vec3_t mins, vec3_t maxs, vec3_t cmaxs, ve
/*
==============
+BG_FindZOffsetForClass
+==============
+*/
+float BG_FindZOffsetForClass( int pclass )
+{
+ int i;
+
+ if( bg_classOverrideList[ pclass ].zOffset != 0.0f )
+ return bg_classOverrideList[ pclass ].zOffset;
+
+ for( i = 0; i < bg_numPclasses; i++ )
+ {
+ if( bg_classList[ i ].classNum == pclass )
+ {
+ return bg_classList[ i ].zOffset;
+ }
+ }
+
+ Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindZOffsetForClass\n" );
+ return 0.0f;
+}
+
+/*
+==============
BG_FindViewheightForClass
==============
*/
@@ -2262,6 +2564,231 @@ int BG_FindValueOfClass( int pclass )
return 0;
}
+/*
+==============
+BG_FindOverrideForClass
+==============
+*/
+static classAttributeOverrides_t *BG_FindOverrideForClass( int pclass )
+{
+ return &bg_classOverrideList[ pclass ];
+}
+
+/*
+======================
+BG_ParseClassFile
+
+Parses a configuration file describing a class
+======================
+*/
+static qboolean BG_ParseClassFile( const char *filename, classAttributeOverrides_t *cao )
+{
+ char *text_p;
+ int i;
+ int len;
+ char *token;
+ char text[ 20000 ];
+ fileHandle_t f;
+ float scale = 0.0f;
+
+
+ // load the file
+ len = trap_FS_FOpenFile( filename, &f, FS_READ );
+ if( len <= 0 )
+ return qfalse;
+
+ if( len >= sizeof( text ) - 1 )
+ {
+ Com_Printf( S_COLOR_RED "ERROR: Class file %s too long\n", filename );
+ return qfalse;
+ }
+
+ trap_FS_Read( text, len, f );
+ text[ len ] = 0;
+ trap_FS_FCloseFile( f );
+
+ // parse the text
+ text_p = text;
+
+ // read optional parameters
+ while( 1 )
+ {
+ token = COM_Parse( &text_p );
+
+ if( !token )
+ break;
+
+ if( !Q_stricmp( token, "" ) )
+ break;
+
+ if( !Q_stricmp( token, "model" ) )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ Q_strncpyz( cao->modelName, token, sizeof( cao->modelName ) );
+
+ continue;
+ }
+ else if( !Q_stricmp( token, "skin" ) )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ Q_strncpyz( cao->skinName, token, sizeof( cao->skinName ) );
+
+ continue;
+ }
+ else if( !Q_stricmp( token, "hud" ) )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ Q_strncpyz( cao->hudName, token, sizeof( cao->hudName ) );
+
+ continue;
+ }
+ else if( !Q_stricmp( token, "modelScale" ) )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ scale = atof( token );
+
+ if( scale < 0.0f )
+ scale = 0.0f;
+
+ cao->modelScale = scale;
+
+ continue;
+ }
+ else if( !Q_stricmp( token, "shadowScale" ) )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ scale = atof( token );
+
+ if( scale < 0.0f )
+ scale = 0.0f;
+
+ cao->shadowScale = scale;
+
+ continue;
+ }
+ else if( !Q_stricmp( token, "mins" ) )
+ {
+ for( i = 0; i <= 2; i++ )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ cao->mins[ i ] = atof( token );
+ }
+
+ continue;
+ }
+ else if( !Q_stricmp( token, "maxs" ) )
+ {
+ for( i = 0; i <= 2; i++ )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ cao->maxs[ i ] = atof( token );
+ }
+
+ continue;
+ }
+ else if( !Q_stricmp( token, "deadMins" ) )
+ {
+ for( i = 0; i <= 2; i++ )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ cao->deadMins[ i ] = atof( token );
+ }
+
+ continue;
+ }
+ else if( !Q_stricmp( token, "deadMaxs" ) )
+ {
+ for( i = 0; i <= 2; i++ )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ cao->deadMaxs[ i ] = atof( token );
+ }
+
+ continue;
+ }
+ else if( !Q_stricmp( token, "crouchMaxs" ) )
+ {
+ for( i = 0; i <= 2; i++ )
+ {
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ cao->crouchMaxs[ i ] = atof( token );
+ }
+
+ continue;
+ }
+ else if( !Q_stricmp( token, "zOffset" ) )
+ {
+ float offset;
+
+ token = COM_Parse( &text_p );
+ if( !token )
+ break;
+
+ offset = atof( token );
+
+ cao->zOffset = offset;
+
+ continue;
+ }
+
+
+ Com_Printf( S_COLOR_RED "ERROR: unknown token '%s'\n", token );
+ return qfalse;
+ }
+
+ return qtrue;
+}
+
+/*
+===============
+BG_InitClassOverrides
+
+Set any overrides specfied by file
+===============
+*/
+void BG_InitClassOverrides( void )
+{
+ int i;
+ classAttributeOverrides_t *cao;
+
+ for( i = PCL_NONE + 1; i < PCL_NUM_CLASSES; i++ )
+ {
+ cao = BG_FindOverrideForClass( i );
+
+ BG_ParseClassFile( va( "overrides/classes/%s.cfg", BG_FindNameForClassNum( i ) ), cao );
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
weaponAttributes_t bg_weapons[ ] =
diff --git a/src/game/bg_pmove.c b/src/game/bg_pmove.c
index 7001abb9..119b3d46 100644
--- a/src/game/bg_pmove.c
+++ b/src/game/bg_pmove.c
@@ -3089,9 +3089,14 @@ void PM_UpdateViewAngles( playerState_t *ps, const usercmd_t *cmd )
//pull the view into the lock point
if( ps->pm_type == PM_GRABBED )
{
+ vec3_t dir, angles;
+
+ ByteToDir( ps->stats[ STAT_VIEWLOCK ], dir );
+ vectoangles( dir, angles );
+
for( i = 0; i < 3; i++ )
{
- float diff = AngleSubtract( ps->viewangles[ i ], ps->grapplePoint[ i ] );
+ float diff = AngleSubtract( ps->viewangles[ i ], angles[ i ] );
while( diff > 180.0f )
diff -= 360.0f;
diff --git a/src/game/bg_public.h b/src/game/bg_public.h
index 0e256ca1..84184b2c 100644
--- a/src/game/bg_public.h
+++ b/src/game/bg_public.h
@@ -209,7 +209,8 @@ typedef enum
STAT_MISC, //TA: for uh...misc stuff
STAT_BUILDABLE, //TA: which ghost model to display for building
STAT_BOOSTTIME, //TA: time left for boost (alien only)
- STAT_FALLDIST //TA: the distance the player fell
+ STAT_FALLDIST, //TA: the distance the player fell
+ STAT_VIEWLOCK //TA: direction to lock the view in
} statIndex_t;
#define SCA_WALLCLIMBER 0x00000001
@@ -866,6 +867,7 @@ typedef struct
char *modelName;
float modelScale;
char *skinName;
+ float shadowScale;
char *hudName;
@@ -876,6 +878,7 @@ typedef struct
vec3_t crouchMaxs;
vec3_t deadMins;
vec3_t deadMaxs;
+ float zOffset;
int viewheight;
int crouchViewheight;
@@ -907,6 +910,22 @@ typedef struct
int value;
} classAttributes_t;
+typedef struct
+{
+ char modelName[ MAX_QPATH ];
+ float modelScale;
+ char skinName[ MAX_QPATH ];
+ float shadowScale;
+ char hudName[ MAX_QPATH ];
+
+ vec3_t mins;
+ vec3_t maxs;
+ vec3_t crouchMaxs;
+ vec3_t deadMins;
+ vec3_t deadMaxs;
+ float zOffset;
+} classAttributeOverrides_t;
+
//stages
typedef enum
{
@@ -930,6 +949,7 @@ typedef struct
vec3_t mins;
vec3_t maxs;
+ float zOffset;
trType_t traj;
float bounce;
@@ -968,6 +988,15 @@ typedef struct
qboolean reactorTest;
} buildableAttributes_t;
+typedef struct
+{
+ char models[ MAX_QPATH ][ MAX_BUILDABLE_MODELS ];
+
+ vec3_t mins;
+ vec3_t maxs;
+ float zOffset;
+} buildableAttributeOverrides_t;
+
//TA: weapon record
typedef struct
{
@@ -1047,6 +1076,7 @@ char *BG_FindHumanNameForBuildable( int bclass );
char *BG_FindEntityNameForBuildable( int bclass );
char *BG_FindModelsForBuildable( int bclass, int modelNum );
void BG_FindBBoxForBuildable( int bclass, vec3_t mins, vec3_t maxs );
+float BG_FindZOffsetForBuildable( int pclass );
int BG_FindHealthForBuildable( int bclass );
int BG_FindRegenRateForBuildable( int bclass );
trType_t BG_FindTrajectoryForBuildable( int bclass );
@@ -1071,6 +1101,7 @@ int BG_FindCreepTestForBuildable( int bclass );
int BG_FindCreepSizeForBuildable( int bclass );
int BG_FindDCCTestForBuildable( int bclass );
int BG_FindUniqueTestForBuildable( int bclass );
+void BG_InitBuildableOverrides( void );
int BG_FindClassNumForName( char *name );
char *BG_FindNameForClassNum( int pclass );
@@ -1078,9 +1109,11 @@ char *BG_FindHumanNameForClassNum( int pclass );
char *BG_FindModelNameForClass( int pclass );
float BG_FindModelScaleForClass( int pclass );
char *BG_FindSkinNameForClass( int pclass );
+float BG_FindShadowScaleForClass( int pclass );
char *BG_FindHudNameForClass( int pclass );
qboolean BG_FindStagesForClass( int pclass, stage_t stage );
void BG_FindBBoxForClass( int pclass, vec3_t mins, vec3_t maxs, vec3_t cmaxs, vec3_t dmins, vec3_t dmaxs );
+float BG_FindZOffsetForClass( int pclass );
void BG_FindViewheightForClass( int pclass, int *viewheight, int *cViewheight );
int BG_FindHealthForClass( int pclass );
float BG_FindFallDamageForClass( int pclass );
@@ -1100,6 +1133,7 @@ weapon_t BG_FindStartWeaponForClass( int pclass );
float BG_FindBuildDistForClass( int pclass );
int BG_ClassCanEvolveFromTo( int fclass, int tclass, int credits, int num );
int BG_FindValueOfClass( int pclass );
+void BG_InitClassOverrides( void );
int BG_FindPriceForWeapon( int weapon );
qboolean BG_FindStagesForWeapon( int weapon, stage_t stage );
diff --git a/src/game/g_main.c b/src/game/g_main.c
index 55b2e39c..31b45e09 100644
--- a/src/game/g_main.c
+++ b/src/game/g_main.c
@@ -436,7 +436,6 @@ static void G_GenerateParticleFileList( void )
}
}
-
/*
============
G_InitGame
@@ -517,6 +516,8 @@ void G_InitGame( int levelTime, int randomSeed, int restart )
G_FindTeams( );
//TA:
+ BG_InitClassOverrides( );
+ BG_InitBuildableOverrides( );
G_InitDamageLocations( );
G_GenerateParticleFileList( );
G_InitMapRotations( );
diff --git a/src/game/g_missile.c b/src/game/g_missile.c
index ac2a46e8..b30f2c3f 100644
--- a/src/game/g_missile.c
+++ b/src/game/g_missile.c
@@ -102,6 +102,7 @@ void G_MissileImpact( gentity_t *ent, trace_t *trace )
{
gentity_t *other, *attacker;
qboolean returnAfterDamage = qfalse;
+ vec3_t dir;
other = &g_entities[ trace->entityNum ];
attacker = &g_entities[ ent->r.ownerNum ];
@@ -125,7 +126,8 @@ void G_MissileImpact( gentity_t *ent, trace_t *trace )
{
other->client->ps.stats[ STAT_STATE ] |= SS_BLOBLOCKED;
other->client->lastLockTime = level.time;
- VectorCopy( other->client->ps.viewangles, other->client->ps.grapplePoint );
+ AngleVectors( other->client->ps.viewangles, dir, NULL, NULL );
+ other->client->ps.stats[ STAT_VIEWLOCK ] = DirToByte( dir );
}
}
else if( !strcmp( ent->classname, "slowblob" ) )
@@ -134,7 +136,8 @@ void G_MissileImpact( gentity_t *ent, trace_t *trace )
{
other->client->ps.stats[ STAT_STATE ] |= SS_SLOWLOCKED;
other->client->lastSlowTime = level.time;
- VectorCopy( other->client->ps.viewangles, other->client->ps.grapplePoint );
+ AngleVectors( other->client->ps.viewangles, dir, NULL, NULL );
+ other->client->ps.stats[ STAT_VIEWLOCK ] = DirToByte( dir );
}
}
else if( !strcmp( ent->classname, "hive" ) )
@@ -598,7 +601,7 @@ gentity_t *fire_lockblob( gentity_t *self, vec3_t start, vec3_t dir )
bolt->s.eType = ET_MISSILE;
bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN;
bolt->s.weapon = WP_LOCKBLOB_LAUNCHER;
- bolt->s.generic1 = self->s.generic1; //weaponMode
+ bolt->s.generic1 = WPM_PRIMARY; //weaponMode
bolt->r.ownerNum = self->s.number;
bolt->parent = self;
bolt->damage = 0;
diff --git a/src/game/g_weapon.c b/src/game/g_weapon.c
index 6adf48a1..4dd1d67e 100644
--- a/src/game/g_weapon.c
+++ b/src/game/g_weapon.c
@@ -638,7 +638,7 @@ CheckGrabAttack
void CheckGrabAttack( gentity_t *ent )
{
trace_t tr;
- vec3_t end;
+ vec3_t end, dir;
gentity_t *traceEnt;
// set aiming directions
@@ -664,7 +664,10 @@ void CheckGrabAttack( gentity_t *ent )
return;
if( !( traceEnt->client->ps.stats[ STAT_STATE ] & SS_GRABBED ) )
- VectorCopy( traceEnt->client->ps.viewangles, traceEnt->client->ps.grapplePoint );
+ {
+ AngleVectors( traceEnt->client->ps.viewangles, dir, NULL, NULL );
+ traceEnt->client->ps.stats[ STAT_VIEWLOCK ] = DirToByte( dir );
+ }
traceEnt->client->ps.stats[ STAT_STATE ] |= SS_GRABBED;
traceEnt->client->lastGrabTime = level.time;