summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cgame/cg_buildable.c135
-rw-r--r--src/game/bg_misc.c51
-rw-r--r--src/game/bg_public.h5
-rw-r--r--src/game/g_active.c2
-rw-r--r--src/game/g_buildable.c39
-rw-r--r--src/game/g_cmds.c6
-rw-r--r--src/game/g_local.h2
-rw-r--r--src/game/g_weapon.c2
-rw-r--r--src/game/tremulous.h8
9 files changed, 126 insertions, 124 deletions
diff --git a/src/cgame/cg_buildable.c b/src/cgame/cg_buildable.c
index 0cf39a86..d5f6871e 100644
--- a/src/cgame/cg_buildable.c
+++ b/src/cgame/cg_buildable.c
@@ -687,7 +687,49 @@ static void CG_BuildableAnimation( centity_t *cent, int *old, int *now, float *b
}
}
-#define TRACE_DEPTH 128.0f
+#define TRACE_DEPTH 64.0f
+
+/*
+===============
+CG_PositionAndOrientateBuildable
+===============
+*/
+static void CG_PositionAndOrientateBuildable( const vec3_t angles, const vec3_t inOrigin,
+ const vec3_t normal, const int skipNumber,
+ const vec3_t mins, const vec3_t maxs,
+ vec3_t outAxis[ 3 ], vec3_t outOrigin )
+{
+ vec3_t forward, start, end;
+ trace_t tr;
+
+ AngleVectors( angles, forward, NULL, NULL );
+ VectorCopy( normal, outAxis[ 2 ] );
+ ProjectPointOnPlane( outAxis[ 0 ], forward, outAxis[ 2 ] );
+
+ if( !VectorNormalize( outAxis[ 0 ] ) )
+ {
+ AngleVectors( angles, NULL, NULL, forward );
+ ProjectPointOnPlane( outAxis[ 0 ], forward, outAxis[ 2 ] );
+ VectorNormalize( outAxis[ 0 ] );
+ }
+
+ CrossProduct( outAxis[ 0 ], outAxis[ 2 ], outAxis[ 1 ] );
+ outAxis[ 1 ][ 0 ] = -outAxis[ 1 ][ 0 ];
+ outAxis[ 1 ][ 1 ] = -outAxis[ 1 ][ 1 ];
+ outAxis[ 1 ][ 2 ] = -outAxis[ 1 ][ 2 ];
+
+ VectorMA( inOrigin, -TRACE_DEPTH, normal, end );
+ VectorMA( inOrigin, 1.0f, normal, start );
+ CG_CapTrace( &tr, start, mins, maxs, end, skipNumber, MASK_PLAYERSOLID );
+
+ if( tr.fraction == 1.0f )
+ {
+ //erm we missed completely - try again with a box trace
+ CG_Trace( &tr, start, mins, maxs, end, skipNumber, MASK_PLAYERSOLID );
+ }
+
+ VectorMA( inOrigin, tr.fraction * -TRACE_DEPTH, normal, outOrigin );
+}
/*
==================
@@ -705,61 +747,14 @@ void CG_GhostBuildable( buildable_t buildable )
ps = &cg.predictedPlayerState;
- memset ( &ent, 0, sizeof( ent ) );
-
- if( cg.predictedPlayerState.stats[ STAT_STATE ] & SS_WALLCLIMBING )
- {
- if( cg.predictedPlayerState.stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING )
- VectorSet( normal, 0.0f, 0.0f, -1.0f );
- else
- VectorCopy( cg.predictedPlayerState.grapplePoint, normal );
- }
- else
- VectorSet( normal, 0.0f, 0.0f, 1.0f );
-
- VectorCopy( cg.predictedPlayerState.viewangles, angles );
-
- AngleVectors( angles, forward, NULL, NULL );
- CrossProduct( forward, normal, cross );
- VectorNormalize( cross );
- CrossProduct( normal, cross, forward );
- VectorNormalize( forward );
-
- VectorCopy( ps->origin, player_origin );
-
- distance = BG_FindBuildDistForClass( ps->stats[ STAT_PCLASS ] );
- VectorMA( player_origin, distance, forward, entity_origin );
-
- VectorCopy( entity_origin, target_origin );
- VectorMA( entity_origin, 32, normal, entity_origin );
- VectorMA( target_origin, -128, normal, target_origin );
+ memset( &ent, 0, sizeof( ent ) );
BG_FindBBoxForBuildable( buildable, mins, maxs );
-
- CG_Trace( &tr, entity_origin, mins, maxs, target_origin, ps->clientNum, MASK_PLAYERSOLID );
- VectorCopy( tr.endpos, entity_origin );
- VectorMA( entity_origin, 0.1f, normal, entity_origin );
- AngleVectors( angles, forward, NULL, NULL );
- VectorCopy( tr.plane.normal, ent.axis[ 2 ] );
- ProjectPointOnPlane( ent.axis[ 0 ], forward, ent.axis[ 2 ] );
-
- if( !VectorNormalize( ent.axis[ 0 ] ) )
- {
- AngleVectors( angles, NULL, NULL, forward );
- ProjectPointOnPlane( ent.axis[ 0 ], forward, ent.axis[ 2 ] );
- VectorNormalize( ent.axis[ 0 ] );
- }
-
- CrossProduct( ent.axis[ 0 ], ent.axis[ 2 ], ent.axis[ 1 ] );
- ent.axis[ 1 ][ 0 ] = -ent.axis[ 1 ][ 0 ];
- ent.axis[ 1 ][ 1 ] = -ent.axis[ 1 ][ 1 ];
- ent.axis[ 1 ][ 2 ] = -ent.axis[ 1 ][ 2 ];
+ BG_PositionBuildableRelativeToPlayer( ps, mins, maxs, CG_Trace, entity_origin, angles, &tr );
- VectorMA( entity_origin, -TRACE_DEPTH, tr.plane.normal, end );
- VectorMA( entity_origin, 1.0f, tr.plane.normal, start );
- CG_CapTrace( &tr, start, mins, maxs, end, ps->clientNum, MASK_PLAYERSOLID );
- VectorMA( entity_origin, tr.fraction * -TRACE_DEPTH, tr.plane.normal, ent.origin );
+ CG_PositionAndOrientateBuildable( ps->viewangles, entity_origin, tr.plane.normal, ps->clientNum,
+ mins, maxs, ent.axis, ent.origin );
//offset on the Z axis if required
VectorMA( ent.origin, BG_FindZOffsetForBuildable( buildable ), tr.plane.normal, ent.origin );
@@ -912,10 +907,9 @@ void CG_Buildable( centity_t *cent )
refEntity_t ent;
entityState_t *es = &cent->currentState;
vec3_t angles;
- vec3_t forward, surfNormal, xNormal, end, start, mins, maxs;
+ vec3_t forward, surfNormal, xNormal, mins, maxs;
vec3_t refNormal = { 0.0f, 0.0f, 1.0f };
float rotAngle;
- trace_t tr;
buildableTeam_t team = BG_FindTeamForBuildable( es->modelindex );
//must be before EF_NODRAW check
@@ -938,36 +932,13 @@ void CG_Buildable( centity_t *cent )
VectorCopy( cent->lerpOrigin, ent.lightingOrigin );
VectorCopy( es->origin2, surfNormal );
- CrossProduct( surfNormal, refNormal, xNormal );
- VectorNormalize( xNormal );
- rotAngle = RAD2DEG( acos( DotProduct( surfNormal, refNormal ) ) );
VectorCopy( es->angles, angles );
BG_FindBBoxForBuildable( es->modelindex, mins, maxs );
-
- AngleVectors( angles, forward, NULL, NULL );
- VectorCopy( surfNormal, ent.axis[ 2 ] );
- ProjectPointOnPlane( ent.axis[ 0 ], forward, ent.axis[ 2 ] );
- if( !VectorNormalize( ent.axis[ 0 ] ) )
- {
- AngleVectors( angles, NULL, NULL, forward );
- ProjectPointOnPlane( ent.axis[ 0 ], forward, ent.axis[ 2 ] );
- VectorNormalize( ent.axis[ 0 ] );
- }
-
- CrossProduct( ent.axis[ 0 ], ent.axis[ 2 ], ent.axis[ 1 ] );
- ent.axis[ 1 ][ 0 ] = -ent.axis[ 1 ][ 0 ];
- ent.axis[ 1 ][ 1 ] = -ent.axis[ 1 ][ 1 ];
- ent.axis[ 1 ][ 2 ] = -ent.axis[ 1 ][ 2 ];
-
if( es->pos.trType == TR_STATIONARY )
- {
- VectorMA( ent.origin, -TRACE_DEPTH, surfNormal, end );
- VectorMA( ent.origin, 1.0f, surfNormal, start );
- CG_CapTrace( &tr, start, mins, maxs, end, es->number, MASK_PLAYERSOLID );
- VectorMA( ent.origin, tr.fraction * -TRACE_DEPTH, surfNormal, ent.origin );
- }
+ CG_PositionAndOrientateBuildable( angles, ent.origin, surfNormal, es->number,
+ mins, maxs, ent.axis, ent.origin );
//offset on the Z axis if required
VectorMA( ent.origin, BG_FindZOffsetForBuildable( es->modelindex ), surfNormal, ent.origin );
@@ -996,9 +967,13 @@ void CG_Buildable( centity_t *cent )
CG_BuildableAnimation( cent, &ent.oldframe, &ent.frame, &ent.backlerp );
- // add to refresh list
+ //add to refresh list
trap_R_AddRefEntityToScene( &ent );
+ CrossProduct( surfNormal, refNormal, xNormal );
+ VectorNormalize( xNormal );
+ rotAngle = RAD2DEG( acos( DotProduct( surfNormal, refNormal ) ) );
+
//turret barrel bit
if( cg_buildables[ es->modelindex ].models[ 1 ] )
{
diff --git a/src/game/bg_misc.c b/src/game/bg_misc.c
index a53b8472..167ce0d5 100644
--- a/src/game/bg_misc.c
+++ b/src/game/bg_misc.c
@@ -4768,3 +4768,54 @@ qboolean BG_rotateAxis( vec3_t surfNormal, vec3_t inAxis[ 3 ],
return qtrue;
}
+
+/*
+===============
+BG_PositionBuildableRelativeToPlayer
+
+Find a place to build a buildable
+===============
+*/
+void BG_PositionBuildableRelativeToPlayer( const playerState_t *ps,
+ const vec3_t mins, const vec3_t maxs,
+ void (*trace)( trace_t *, const vec3_t, const vec3_t,
+ const vec3_t, const vec3_t, int, int ),
+ vec3_t outOrigin, vec3_t outAngles, trace_t *tr )
+{
+ vec3_t forward, entityOrigin, targetOrigin;
+ vec3_t angles, playerOrigin, playerNormal;
+ float buildDist;
+
+ if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBING )
+ {
+ if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING )
+ VectorSet( playerNormal, 0.0f, 0.0f, -1.0f );
+ else
+ VectorCopy( ps->grapplePoint, playerNormal );
+ }
+ else
+ VectorSet( playerNormal, 0.0f, 0.0f, 1.0f );
+
+ VectorCopy( ps->viewangles, angles );
+ VectorCopy( ps->origin, playerOrigin );
+ buildDist = BG_FindBuildDistForClass( ps->stats[ STAT_PCLASS ] );
+
+ AngleVectors( angles, forward, NULL, NULL );
+ ProjectPointOnPlane( forward, forward, playerNormal );
+ VectorNormalize( forward );
+
+ VectorMA( playerOrigin, buildDist, forward, entityOrigin );
+
+ VectorCopy( entityOrigin, targetOrigin );
+
+ //so buildings can be placed facing slopes
+ VectorMA( entityOrigin, 32, playerNormal, entityOrigin );
+
+ //so buildings drop to floor
+ VectorMA( targetOrigin, -128, playerNormal, targetOrigin );
+
+ (*trace)( tr, entityOrigin, mins, maxs, targetOrigin, ps->clientNum, MASK_PLAYERSOLID );
+ VectorCopy( tr->endpos, entityOrigin );
+ VectorMA( entityOrigin, 0.1f, playerNormal, outOrigin );
+ vectoangles( forward, outAngles );
+}
diff --git a/src/game/bg_public.h b/src/game/bg_public.h
index 822306a0..02ffad71 100644
--- a/src/game/bg_public.h
+++ b/src/game/bg_public.h
@@ -1067,6 +1067,11 @@ void BG_deactivateItem( int item, int stats[ ] );
qboolean BG_activated( int item, int stats[ ] );
qboolean BG_rotateAxis( vec3_t surfNormal, vec3_t inAxis[ 3 ],
vec3_t outAxis[ 3 ], qboolean inverse, qboolean ceiling );
+void BG_PositionBuildableRelativeToPlayer( const playerState_t *ps,
+ const vec3_t mins, const vec3_t maxs,
+ void (*trace)( trace_t *, const vec3_t, const vec3_t,
+ const vec3_t, const vec3_t, int, int ),
+ vec3_t outOrigin, vec3_t outAngles, trace_t *tr );
int BG_FindBuildNumForName( char *name );
int BG_FindBuildNumForEntityName( char *name );
diff --git a/src/game/g_active.c b/src/game/g_active.c
index 516bac5a..9a1e625c 100644
--- a/src/game/g_active.c
+++ b/src/game/g_active.c
@@ -361,7 +361,7 @@ void SpectatorThink( gentity_t *ent, usercmd_t *ucmd )
}
if( ( client->buttons & BUTTON_USE_HOLDABLE ) && !( client->oldbuttons & BUTTON_USE_HOLDABLE ) )
- Cmd_Follow_f( ent );
+ Cmd_Follow_f( ent, qtrue );
}
diff --git a/src/game/g_buildable.c b/src/game/g_buildable.c
index ac9b3cbd..fba8a54a 100644
--- a/src/game/g_buildable.c
+++ b/src/game/g_buildable.c
@@ -2214,10 +2214,9 @@ Checks to see if an item fits in a specific area
*/
itemBuildError_t G_itemFits( gentity_t *ent, buildable_t buildable, int distance, vec3_t origin )
{
- vec3_t forward, angles;
- vec3_t player_origin, entity_origin, target_origin, normal, cross;
+ vec3_t angles;
+ vec3_t entity_origin, normal;
vec3_t mins, maxs;
- vec3_t temp_v;
trace_t tr1, tr2, tr3;
int i;
itemBuildError_t reason = IBE_NONE;
@@ -2226,44 +2225,16 @@ itemBuildError_t G_itemFits( gentity_t *ent, buildable_t buildable, int distance
int templength;
float minNormal;
qboolean invert;
-
- if( ent->client->ps.stats[ STAT_STATE ] & SS_WALLCLIMBING )
- {
- if( ent->client->ps.stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING )
- VectorSet( normal, 0.0f, 0.0f, -1.0f );
- else
- VectorCopy( ent->client->ps.grapplePoint, normal );
- }
- else
- VectorSet( normal, 0.0f, 0.0f, 1.0f );
-
- //FIXME: must sync with cg_buildable.c/CG_GhostBuildable ick.
- VectorCopy( ent->s.apos.trBase, angles );
-
- AngleVectors( angles, forward, NULL, NULL );
- CrossProduct( forward, normal, cross );
- VectorNormalize( cross );
- CrossProduct( normal, cross, forward );
- VectorNormalize( forward );
-
- VectorCopy( ent->s.pos.trBase, player_origin );
- VectorMA( player_origin, distance, forward, entity_origin );
-
- VectorCopy( entity_origin, target_origin );
- VectorMA( entity_origin, 32, normal, entity_origin );
- VectorMA( target_origin, -128, normal, target_origin );
+ playerState_t *ps = &ent->client->ps;
BG_FindBBoxForBuildable( buildable, mins, maxs );
- trap_Trace( &tr1, entity_origin, mins, maxs, target_origin, ent->s.number, MASK_PLAYERSOLID );
- VectorCopy( tr1.endpos, entity_origin );
- VectorMA( entity_origin, 0.1f, normal, entity_origin );
+ BG_PositionBuildableRelativeToPlayer( ps, mins, maxs, trap_Trace, entity_origin, angles, &tr1 );
trap_Trace( &tr2, entity_origin, mins, maxs, entity_origin, ent->s.number, MASK_PLAYERSOLID );
- trap_Trace( &tr3, player_origin, NULL, NULL, entity_origin, ent->s.number, MASK_PLAYERSOLID );
+ trap_Trace( &tr3, ps->origin, NULL, NULL, entity_origin, ent->s.number, MASK_PLAYERSOLID );
VectorCopy( entity_origin, origin );
- vectoangles( forward, angles );
//this item does not fit here
if( tr2.fraction < 1.0 || tr3.fraction < 1.0 )
diff --git a/src/game/g_cmds.c b/src/game/g_cmds.c
index 5762d3f0..b2d56731 100644
--- a/src/game/g_cmds.c
+++ b/src/game/g_cmds.c
@@ -1830,12 +1830,12 @@ void G_StopFollowing( gentity_t *ent )
Cmd_Follow_f
=================
*/
-void Cmd_Follow_f( gentity_t *ent )
+void Cmd_Follow_f( gentity_t *ent, qboolean toggle )
{
int i;
char arg[ MAX_TOKEN_CHARS ];
- if( trap_Argc( ) != 2 )
+ if( trap_Argc( ) != 2 || toggle )
{
if( ent->client->sess.spectatorState == SPECTATOR_FOLLOW )
G_StopFollowing( ent );
@@ -2067,7 +2067,7 @@ void ClientCommand( int clientNum )
else if( Q_stricmp( cmd, "callteamvote" ) == 0 )
Cmd_CallTeamVote_f( ent );
else if( Q_stricmp( cmd, "follow" ) == 0 )
- Cmd_Follow_f( ent );
+ Cmd_Follow_f( ent, qfalse );
else if( Q_stricmp (cmd, "follownext") == 0)
Cmd_FollowCycle_f( ent, 1 );
else if( Q_stricmp( cmd, "followprev" ) == 0 )
diff --git a/src/game/g_local.h b/src/game/g_local.h
index 5f73424d..34491015 100644
--- a/src/game/g_local.h
+++ b/src/game/g_local.h
@@ -565,7 +565,7 @@ char *G_NewString( const char *string );
//
void Cmd_Score_f( gentity_t *ent );
void G_StopFollowing( gentity_t *ent );
-void Cmd_Follow_f( gentity_t *ent );
+void Cmd_Follow_f( gentity_t *ent, qboolean toggle );
//
// g_physics.c
diff --git a/src/game/g_weapon.c b/src/game/g_weapon.c
index 2c24c58c..850ccd72 100644
--- a/src/game/g_weapon.c
+++ b/src/game/g_weapon.c
@@ -575,7 +575,7 @@ void cancelBuildFire( gentity_t *ent )
( traceEnt->biteam == ent->client->ps.stats[ STAT_PTEAM ] ) &&
( ( ent->client->ps.weapon >= WP_HBUILD2 ) &&
( ent->client->ps.weapon <= WP_HBUILD ) ) &&
- traceEnt->spawned )
+ traceEnt->spawned && traceEnt->health > 0 )
{
if( ent->client->ps.stats[ STAT_MISC ] > 0 )
{
diff --git a/src/game/tremulous.h b/src/game/tremulous.h
index fa8a1e71..a7b943ff 100644
--- a/src/game/tremulous.h
+++ b/src/game/tremulous.h
@@ -307,7 +307,7 @@
*
*/
-#define HUMAN_WDMG_MODIFIER 1.0f
+#define HUMAN_WDMG_MODIFIER 1.05f
#define HDM(d) ((int)((float)d*HUMAN_WDMG_MODIFIER))
#define BLASTER_REPEAT 600
@@ -469,14 +469,14 @@
#define MGTURRET_HEALTH HBHM(450)
#define MGTURRET_SPLASHDAMAGE 50
#define MGTURRET_SPLASHRADIUS 100
-#define MGTURRET_ANGULARSPEED 5 //degrees/think ~= 200deg/sec
+#define MGTURRET_ANGULARSPEED 6 //degrees/think ~= 200deg/sec
#define MGTURRET_ACCURACYTOLERANCE MGTURRET_ANGULARSPEED / 1.5f //angular difference for turret to fire
#define MGTURRET_VERTICALCAP 30 // +/- maximum pitch
#define MGTURRET_REPEAT 100
#define MGTURRET_RANGE 250
#define MGTURRET_SPREAD 200
#define MGTURRET_DMG HDM(5)
-#define MGTURRET_DCC_ANGULARSPEED 6
+#define MGTURRET_DCC_ANGULARSPEED 7
#define MGTURRET_DCC_ACCURACYTOLERANCE MGTURRET_DCC_ANGULARSPEED / 1.5f
#define TESLAGEN_BP 10
@@ -502,7 +502,7 @@
#define REACTOR_BP 0
#define REACTOR_BT 20000
-#define REACTOR_HEALTH HBHM(1000)
+#define REACTOR_HEALTH HBHM(1500)
#define REACTOR_SPLASHDAMAGE 200
#define REACTOR_SPLASHRADIUS 300
#define REACTOR_VALUE 2