summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cgame/cg_local.h3
-rw-r--r--src/cgame/cg_tutorial.c11
-rw-r--r--src/cgame/cg_view.c56
-rw-r--r--src/game/g_active.c4
4 files changed, 62 insertions, 12 deletions
diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h
index 73933525..87911919 100644
--- a/src/cgame/cg_local.h
+++ b/src/cgame/cg_local.h
@@ -1100,6 +1100,9 @@ typedef struct
vec3_t kick_angles; // weapon kicks
vec3_t kick_origin;
+
+ qboolean thirdPersonFollow;
+
// temp working variables for player view
float bobfracsin;
int bobcycle;
diff --git a/src/cgame/cg_tutorial.c b/src/cgame/cg_tutorial.c
index 4f4608a0..77d0d8fb 100644
--- a/src/cgame/cg_tutorial.c
+++ b/src/cgame/cg_tutorial.c
@@ -574,9 +574,14 @@ static void CG_SpectatorText( char *text, playerState_t *ps )
if( ps->pm_flags & PMF_FOLLOW )
{
- Q_strcat( text, MAX_TUTORIAL_TEXT,
- va( "Press %s to stop following\n",
- CG_KeyNameForCommand( "+button2" ) ) );
+ if( !cg.thirdPersonFollow )
+ Q_strcat( text, MAX_TUTORIAL_TEXT,
+ va( "Press %s to switch to third-person spectator mode\n",
+ CG_KeyNameForCommand( "+button2" ) ) );
+ else
+ Q_strcat( text, MAX_TUTORIAL_TEXT,
+ va( "Press %s to return to free spectator mode\n",
+ CG_KeyNameForCommand( "+button2" ) ) );
Q_strcat( text, MAX_TUTORIAL_TEXT,
va( "Press %s or ",
diff --git a/src/cgame/cg_view.c b/src/cgame/cg_view.c
index 7d4693a8..3e873d9d 100644
--- a/src/cgame/cg_view.c
+++ b/src/cgame/cg_view.c
@@ -277,6 +277,10 @@ static void CG_OffsetThirdPersonView( void )
float focusDist;
float forwardScale, sideScale;
vec3_t surfNormal;
+ float angleOffsets[3];
+ usercmd_t cmd;
+ int cmdNum;
+ int i;
BG_GetClientNormal( &cg.predictedPlayerState, surfNormal );
@@ -284,6 +288,9 @@ static void CG_OffsetThirdPersonView( void )
VectorCopy( cg.refdefViewAngles, focusAngles );
+ cmdNum = trap_GetCurrentCmdNumber();
+ trap_GetUserCmd( cmdNum, &cmd );
+
// if dead, look at killer
if( cg.predictedPlayerState.stats[ STAT_HEALTH ] <= 0 )
{
@@ -306,8 +313,24 @@ static void CG_OffsetThirdPersonView( void )
AngleVectors( cg.refdefViewAngles, forward, right, up );
- forwardScale = cos( cg_thirdPersonAngle.value / 180 * M_PI );
- sideScale = sin( cg_thirdPersonAngle.value / 180 * M_PI );
+ for( i = 0; i < 3; i++ )
+ {
+ if ( cg.snap->ps.pm_flags & PMF_FOLLOW )
+ angleOffsets[ i ] = SHORT2ANGLE(cmd.angles[ i ]);
+ else
+ angleOffsets[ i ] = 0;
+
+ if( i == YAW )
+ angleOffsets[ i ] += cg_thirdPersonAngle.value;
+
+ while( angleOffsets[ i ] > 180.0f )
+ angleOffsets[ i ] -= 360.0f;
+ while( angleOffsets[ i ] < -180.0f )
+ angleOffsets[ i ] += 360.0f;
+ }
+
+ forwardScale = cos( angleOffsets[ YAW ] / 180 * M_PI );
+ sideScale = sin( angleOffsets[ YAW ] / 180 * M_PI );
VectorMA( view, -cg_thirdPersonRange.value * forwardScale, forward, view );
VectorMA( view, -cg_thirdPersonRange.value * sideScale, right, view );
@@ -338,8 +361,11 @@ static void CG_OffsetThirdPersonView( void )
if ( focusDist < 1 ) {
focusDist = 1; // should never happen
}
- cg.refdefViewAngles[ PITCH ] = -180 / M_PI * atan2( focusPoint[ 2 ], focusDist );
- cg.refdefViewAngles[ YAW ] -= cg_thirdPersonAngle.value;
+
+ cg.refdefViewAngles[ PITCH ] = -180 / M_PI * atan2( focusPoint[ 2 ], focusDist ) +
+ angleOffsets[ PITCH ];
+
+ cg.refdefViewAngles[ YAW ] -= angleOffsets[ YAW ];
}
@@ -685,10 +711,29 @@ static int CG_CalcFov( void )
int inwater;
int attribFov;
usercmd_t cmd;
+ usercmd_t oldcmd;
int cmdNum;
cmdNum = trap_GetCurrentCmdNumber( );
trap_GetUserCmd( cmdNum, &cmd );
+ trap_GetUserCmd( cmdNum - 1, &oldcmd );
+
+ // switch follow modes if necessary: cycle between free -> follow -> third-person follow
+ if( cmd.buttons & BUTTON_USE_HOLDABLE && !( oldcmd.buttons & BUTTON_USE_HOLDABLE ) )
+ {
+ if ( cg.snap->ps.pm_flags & PMF_FOLLOW )
+ {
+ if( !cg.thirdPersonFollow )
+ cg.thirdPersonFollow = qtrue;
+ else
+ {
+ cg.thirdPersonFollow = qfalse;
+ trap_SendClientCommand( "follow\n" );
+ }
+ }
+ else if ( cg.snap->ps.persistant[ PERS_SPECSTATE ] != SPECTATOR_NOT )
+ trap_SendClientCommand( "follow\n" );
+ }
if( cg.predictedPlayerState.pm_type == PM_INTERMISSION ||
( cg.snap->ps.persistant[ PERS_SPECSTATE ] != SPECTATOR_NOT ) )
@@ -1232,7 +1277,8 @@ void CG_DrawActiveFrame( int serverTime, stereoFrame_t stereoView, qboolean demo
CG_PredictPlayerState( );
// decide on third person view
- cg.renderingThirdPerson = cg_thirdPerson.integer || ( cg.snap->ps.stats[ STAT_HEALTH ] <= 0 );
+ cg.renderingThirdPerson = ( cg_thirdPerson.integer || ( cg.snap->ps.stats[ STAT_HEALTH ] <= 0 ) ||
+ ( cg.thirdPersonFollow ) );
// build cg.refdef
inwater = CG_CalcViewValues( );
diff --git a/src/game/g_active.c b/src/game/g_active.c
index 84c58996..c5f1bd8e 100644
--- a/src/game/g_active.c
+++ b/src/game/g_active.c
@@ -505,10 +505,6 @@ void SpectatorThink( gentity_t *ent, usercmd_t *ucmd )
}
}
}
-
- // Tertiary fire or use button toggles following mode
- if( attack3 )
- G_ToggleFollow( ent );
}