1
0
mirror of https://github.com/alliedmodders/hl2sdk.git synced 2025-01-05 17:13:36 +08:00
hl2sdk/game/client/swarm/asw_in_camera.cpp
2010-07-22 01:46:14 -05:00

524 lines
18 KiB
C++

#include "cbase.h"
#include "asw_util_shared.h"
#include "c_asw_camera_volume.h"
#include "c_asw_marine.h"
#include "c_asw_player.h"
#include "asw_gamerules.h"
#include "asw_input.h"
#include "missionchooser/iasw_random_missions.h"
#include "holdout_resupply_frame.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// Marine Camera ConVars.
ConVar asw_cam_marine_pitch( "asw_cam_marine_pitch", "60", FCVAR_CHEAT, "Marine Camera: pitch." );
ConVar asw_cam_marine_pitch_rate( "asw_cam_marine_pitch_rate", "1000", FCVAR_CHEAT ); // asw setting
ConVar asw_cam_marine_yaw( "asw_cam_marine_yaw", "90", FCVAR_CHEAT, "Marine Camera: yaw." );
ConVar asw_cam_marine_dist( "asw_cam_marine_dist", "412", FCVAR_CHEAT, "Marine Camera: Distance from marine." );
ConVar asw_cam_marine_dist_rate( "asw_cam_marine_dist_rate", "50", FCVAR_CHEAT, "Marine Camera: Distance from marine." );
ConVar asw_cam_marine_dist_death( "asw_cam_marine_dist_death", "200", FCVAR_CHEAT, "Marine Camera: Distance from marine as he dies." );
ConVar asw_cam_marine_pitch_death( "asw_cam_marine_pitch_death", "50", FCVAR_CHEAT, "Marine Camera: pitch when he dies." );
ConVar asw_cam_marine_yaw_death_rate( "asw_cam_marine_yaw_death_rate", "35.0", FCVAR_CHEAT, "Marine Camera: yaw rotate rate when he dies." );
ConVar asw_cam_marine_shift_z_death( "asw_cam_marine_shift_z_death", "-30.0", FCVAR_CHEAT, "Marine Camera: Shift camera vertically when he dies." );
ConVar asw_cam_marine_shift_ratex( "asw_cam_marine_shift_ratex", "1000", FCVAR_CHEAT, "Marine Camera: How far the camera pans east/west as you move the mouse." );
ConVar asw_cam_marine_shift_ratey( "asw_cam_marine_shift_ratey", "650", FCVAR_CHEAT, "Marine Camera: How far the camera pans north as you move the mouse." );
ConVar asw_cam_marine_shift_ratey_south( "asw_cam_marine_shift_ratey_south", "2000", FCVAR_CHEAT, "Marine Camera: How far the camera pans south as you move the mouse." );
ConVar asw_cam_marine_shift_maxx( "asw_cam_marine_shift_maxx", "300", FCVAR_CHEAT, "Marine Camera: How far the camera pans east/west as you move the mouse." );
ConVar asw_cam_marine_shift_maxy( "asw_cam_marine_shift_maxy", "200", FCVAR_CHEAT, "Marine Camera: How far the camera pans north as you move the mouse." );
ConVar asw_cam_marine_shift_maxy_south( "asw_cam_marine_shift_maxy_south", "380", FCVAR_CHEAT, "Marine Camera: How far the camera pans south as you move the mouse." );
ConVar asw_cam_marine_shift_deadspace( "asw_cam_marine_shift_deadspace", "64", FCVAR_CHEAT, "Marine Camera: Deadspace around the marine before camera shifting starts." );
ConVar asw_cam_marine_blend( "asw_cam_marine_blend", "1", FCVAR_CHEAT, "Marine Camera: Whether camera should blend Z movement changes.");
ConVar asw_cam_marine_test( "asw_cam_marine_test", "1", FCVAR_CHEAT, "Camera Test." );
ConVar asw_cam_marine_sphere_min( "asw_cam_marine_sphere_min", "32", FCVAR_CHEAT, "Test" );
ConVar asw_cam_marine_sphere_max( "asw_cam_marine_sphere_max", "400", FCVAR_CHEAT, "Test" );
ConVar asw_cam_marine_spring_vel_max( "asw_cam_marine_spring_vel_max", "35.0", FCVAR_CHEAT, "Camera max velocity." );
ConVar asw_cam_marine_spring_const( "asw_cam_marine_spring_const", "0.75", FCVAR_CHEAT, "Camera spring constant." );
ConVar asw_cam_marine_spring_dampening( "asw_cam_marine_spring_dampening", "3.0", FCVAR_CHEAT, "Camera spring dampening." );
ConVar asw_cam_marine_yshift_static( "asw_cam_marine_yshift_static", "75.0f", FCVAR_CHEAT, "Camera y-shift value." );
ConVar asw_cam_marine_shift_enable( "asw_cam_marine_shift_enable", "1", FCVAR_CHEAT, "Camera shifting enable/disable." );
// Vehicle Camera ConVars.
ConVar asw_vehicle_cam_height( "asw_vehicle_cam_height", "0", FCVAR_CHEAT );
ConVar asw_vehicle_cam_pitch( "asw_vehicle_cam_pitch", "45", FCVAR_CHEAT );
ConVar asw_vehicle_cam_dist( "asw_vehicle_cam_dist", "412", FCVAR_CHEAT );
// ASWTODO - allow thirdperson but cheat protect first person
//static ConCommand thirdperson( "thirdperson", ::CAM_ToThirdPerson, "Switch to thirdperson camera." );
//static ConCommand firstperson( "firstperson", ::CAM_ToFirstPerson, "Switch to firstperson camera.", FCVAR_CHEAT );
extern kbutton_t in_zoom;
extern ConVar asw_hide_local_marine;
extern ConVar cam_command;
extern ConVar sv_cheats;
extern ConVar joy_pan_camera;
#define DIST 2
// Camera height distances!
float s_flCameraHeights[ASW_TILETYPE_COUNT] =
{
500.0f, // Unknown
600.0f, // Outdoor1
800.0f, // Outdoor2
550.0f, // Arena1
650.0f, // Arena2
750.0f, // Arena3
450.0f, // Room1
550.0f, // Room2
300.0f, // Corridor1
400.0f, // Corridor1
250.0f // Vents
};
float s_flCameraHeights55[ASW_TILETYPE_COUNT] =
{
900.0f, // Unknown
1080.0f, // Outdoor1
1440.0f, // Outdoor2
990.0f, // Arena1
1170.0f, // Arena2
1350.0f, // Arena3
810.0f, // Room1
990.0f, // Room2
540.0f, // Corridor1
720.0f, // Corridor1
450.0f // Vents
};
// Panning to much when pulled further out
//-----------------------------------------------------------------------------
// Purpose: Alien Swarm camera pitch.
//-----------------------------------------------------------------------------
float CASWInput::ASW_GetCameraPitch( const float *pfDeathCamInterp /*= NULL*/ )
{
// Get the given pitch.
float flPitch = asw_cam_marine_pitch.GetFloat();
float fDeathCamInterp;
if ( pfDeathCamInterp )
{
fDeathCamInterp = *pfDeathCamInterp;
}
else
{
fDeathCamInterp = ( ASWGameRules() ? ASWGameRules()->GetMarineDeathCamInterp() : 0.0f );
}
if ( fDeathCamInterp > 0.0f )
{
flPitch = ( 1.0f - fDeathCamInterp ) * flPitch + fDeathCamInterp * asw_cam_marine_pitch_death.GetFloat();
}
// Check to see if we are in a camera volume.
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
if (pPlayer && pPlayer->GetMarine())
{
float fCameraVolumePitch = C_ASW_Camera_Volume::IsPointInCameraVolume( pPlayer->GetMarine()->GetAbsOrigin() );
if ( fCameraVolumePitch != -1 )
{
flPitch = fCameraVolumePitch;
}
}
if ( m_fCurrentCameraPitch != flPitch )
{
float flDelta = MIN( 0.2f, gpGlobals->frametime );
m_fCurrentCameraPitch = ASW_ClampYaw( asw_cam_marine_pitch_rate.GetFloat(), m_fCurrentCameraPitch, flPitch, flDelta );
}
return m_fCurrentCameraPitch;
}
//-----------------------------------------------------------------------------
// Purpose: Alien Swarm camera yaw.
//-----------------------------------------------------------------------------
float CASWInput::ASW_GetCameraYaw( const float *pfDeathCamInterp /*= NULL*/ )
{
float fDeathCamInterp;
if ( pfDeathCamInterp )
{
fDeathCamInterp = *pfDeathCamInterp;
}
else
{
fDeathCamInterp = ( ASWGameRules() ? ASWGameRules()->GetMarineDeathCamInterp() : 0.0f );
}
if ( fDeathCamInterp > 0.0f )
{
float fRotate = gpGlobals->curtime * asw_cam_marine_yaw_death_rate.GetFloat() + ASWGameRules()->m_fDeathCamYawAngleOffset;
float fFullRotations = static_cast< int >( fRotate / 360.0f );
fRotate -= fFullRotations * 360.0f;
fRotate = AngleNormalize( fRotate );
return ( 1.0f - fDeathCamInterp ) * asw_cam_marine_yaw.GetFloat() + fDeathCamInterp * ( asw_cam_marine_yaw.GetFloat() + fRotate );
}
return asw_cam_marine_yaw.GetFloat();
}
extern ConVar fov_desired;
//-----------------------------------------------------------------------------
// Purpose: Alien Swarm camera distance.
//-----------------------------------------------------------------------------
float CASWInput::ASW_GetCameraDist( const float *pfDeathCamInterp /*= NULL*/ )
{
#ifdef VARIABLE_CAMERA
// Are we using a valid FOV, if not use the default distance.
float flFOV = fov_desired.GetFloat();
if ( !( flFOV == 75.0f || flFOV == 50.0f ) )
return asw_cam_marine_dist.GetFloat();
// Do we have a missionchooser, if not use the default distance.
if ( !missionchooser || !missionchooser->RandomMissions() )
return asw_cam_marine_dist.GetFloat();
// Do we have a valid player and marine, if not use the default distance.
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
if ( !pPlayer || !pPlayer->GetMarine() )
return asw_cam_marine_dist.GetFloat();
// Do we have a valid room, if not use the default distance.
IASW_Room_Details *pRoom = missionchooser->RandomMissions()->GetRoomDetails( pPlayer->GetMarine()->GetAbsOrigin() );
if ( !pRoom )
return asw_cam_marine_dist.GetFloat();
// Get the desired distance for the room.
float flDesiredDist = s_flCameraHeights[pRoom->GetTileType()];
if ( flFOV == 50 )
{
flDesiredDist = s_flCameraHeights55[pRoom->GetTileType()];
}
float flCameraDelta = fabs( m_flCurrentCameraDist - flDesiredDist );
// Check against a tolerance so we don't oscillate forever.
if ( flCameraDelta > 0.2f )
{
// Get frametime = delta time
float flFrameTime = gpGlobals->frametime;
float flAccel = fabs( flDesiredDist - m_flCurrentCameraDist ) * asw_cam_marine_spring_const.GetFloat();
float flZDampening = asw_cam_marine_spring_dampening.GetFloat() * m_vecCameraVelocity.z;
flAccel -= flZDampening;
float flZVelocity = flAccel * flFrameTime;
m_vecCameraVelocity.z += flZVelocity;
m_vecCameraVelocity.z = clamp( m_vecCameraVelocity.z, 0.1f, asw_cam_marine_spring_vel_max.GetFloat() );
if ( m_flCurrentCameraDist < flDesiredDist )
{
m_flCurrentCameraDist += m_vecCameraVelocity.z * flFrameTime;
}
else
{
m_flCurrentCameraDist -= m_vecCameraVelocity.z * flFrameTime;
}
}
else
{
m_vecCameraVelocity.z = 0.0f;
m_flCurrentCameraDist = flDesiredDist;
}
return m_flCurrentCameraDist;
#else
float fDeathCamInterp;
if ( pfDeathCamInterp )
{
fDeathCamInterp = *pfDeathCamInterp;
}
else
{
fDeathCamInterp = ( ASWGameRules() ? ASWGameRules()->GetMarineDeathCamInterp() : 0.0f );
}
if ( fDeathCamInterp > 0.0f )
{
return ( 1.0f - fDeathCamInterp ) * asw_cam_marine_dist.GetFloat() + fDeathCamInterp * asw_cam_marine_dist_death.GetFloat();
}
return asw_cam_marine_dist.GetFloat();
#endif
}
extern void UpdateOrderArrow();
void CASWInput::CAM_Think( void )
{
Assert( engine->IsLocalPlayerResolvable() );
UpdateOrderArrow(); // update the arrow direction if we're in the middle of ordering a marine (see in_main.cpp)
switch( GetPerUser().m_nCamCommand )
{
case CAM_COMMAND_TOTHIRDPERSON:
CAM_ToThirdPerson();
break;
case CAM_COMMAND_TOFIRSTPERSON:
CAM_ToFirstPerson();
break;
case CAM_COMMAND_NONE:
default:
break;
}
if( !GetPerUser().m_fCameraInThirdPerson )
return;
GetPerUser().m_vecCameraOffset[ PITCH ] = ASW_GetCameraPitch();
GetPerUser().m_vecCameraOffset[ YAW ] = ASW_GetCameraYaw();
GetPerUser().m_vecCameraOffset[ DIST ] = 0;
}
void CASWInput::CAM_ToThirdPerson(void)
{
asw_hide_local_marine.SetValue(0);
CInput::CAM_ToThirdPerson();
}
void CASWInput::CAM_ToFirstPerson(void)
{
asw_hide_local_marine.SetValue(1);
CInput::CAM_ToFirstPerson();
}
extern int g_asw_iPlayerListOpen;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CASWInput::CalculateCameraShift( C_ASW_Player *pPlayer, float flDeltaX, float flDeltaY, float &flShiftX, float &flShiftY )
{
// Init.
flShiftX = 0.0f;
flShiftY = 0.0f;
if ( !asw_cam_marine_shift_enable.GetBool() )
return;
if ( m_bCameraFixed || Holdout_Resupply_Frame::HasResupplyFrameOpen() || g_asw_iPlayerListOpen > 0 || ( pPlayer && pPlayer->GetSpectatingMarine() ) )
{
m_fShiftFraction = Approach( 0.0f, m_fShiftFraction, gpGlobals->frametime );
}
else
{
m_fShiftFraction = Approach( 1.0f, m_fShiftFraction, gpGlobals->frametime );
}
if ( ASWGameRules() )
{
m_fShiftFraction = m_fShiftFraction * ( 1.0f - ASWGameRules()->GetMarineDeathCamInterp() );
}
flShiftX = flDeltaX * asw_cam_marine_shift_maxx.GetFloat() * m_fShiftFraction;
float camshifty = (flDeltaY < 0) ? asw_cam_marine_shift_maxy.GetFloat() : asw_cam_marine_shift_maxy_south.GetFloat();
flShiftY = flDeltaY * camshifty * m_fShiftFraction;
return;
// Calculate the shift, spherically, based on the cursor distance from the player.
float flDistance = FastSqrt( flDeltaX * flDeltaX + flDeltaY * flDeltaY );
if ( flDistance > asw_cam_marine_sphere_min.GetFloat() )
{
flDistance -= asw_cam_marine_sphere_min.GetFloat();
float flRatio = 1.0f;
if ( m_flCurrentCameraDist < asw_cam_marine_dist.GetFloat() )
{
flRatio = ( m_flCurrentCameraDist / asw_cam_marine_dist.GetFloat() ) * 0.8f;
}
float flTemp = flDistance / ( asw_cam_marine_sphere_max.GetFloat() * flRatio );
flTemp = clamp( flTemp, 0.0f, 1.0f );
float flAngle = atan2( (float)flDeltaY, (float)flDeltaX );
flShiftX = cos( flAngle ) * flTemp * ( asw_cam_marine_shift_maxx.GetFloat() * flRatio );
if ( flDeltaY < 0 )
{
flShiftY = sin( flAngle ) * flTemp * ( asw_cam_marine_shift_maxy.GetFloat() * flRatio );
}
else
{
flShiftY = sin( flAngle ) * flTemp * ( asw_cam_marine_shift_maxy_south.GetFloat() * flRatio );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CASWInput::SmoothCamera( C_ASW_Player *pPlayer, Vector &vecCameraLocation )
{
// Override smoothing enabled.
if ( !asw_cam_marine_blend.GetBool() )
return;
// Apply smoothing from the previous position if we did change marine
if ( !pPlayer->SmoothMarineChangeCamera( vecCameraLocation ) )
{
// Apply Z smoothing to the camera if we didn't change marine.
pPlayer->SmoothCameraZ( vecCameraLocation );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CASWInput::ASW_GetCameraLocation( C_ASW_Player *pPlayer, Vector &vecCameraLocation, QAngle &angCamera, int &nMouseX, int &nMouseY, bool bApplySmoothing )
{
// Verify data.
Assert( pPlayer != NULL );
if ( !pPlayer )
return;
Assert( ASWInput() != NULL );
if ( !ASWInput() )
return;
// If we've already calculated the camera position on this frame, then just return the previous result.
// if ( pPlayer->m_nLastCameraFrame == gpGlobals->framecount )
// {
// vecCameraLocation = pPlayer->m_vecLastCameraPosition;
// angCamera = pPlayer->m_angLastCamera;
// return;
// }
// Get the current camera position.
vecCameraLocation = pPlayer->EyePosition();
// Get the camera angles and calculate the camera view directions.
Vector vecCameraDirection;
::input->CAM_GetCameraOffset( vecCameraDirection );
angCamera[PITCH] = vecCameraDirection[PITCH];
angCamera[YAW] = vecCameraDirection[YAW];
angCamera[ROLL] = 0;
Vector vecCamForward, vecCamRight, vecCamUp;
AngleVectors( angCamera, &vecCamForward, &vecCamRight, &vecCamUp );
// Get the window center.
int nCenterX, nCenterY;
ASWInput()->ASW_GetWindowCenter( nCenterX, nCenterY );
// Get the position change.
int nUnclampedX, nUnclampedY;
ASWInput()->GetSimulatedFullscreenMousePos( &nMouseX, &nMouseY, &nUnclampedX, &nUnclampedY );
// Calculate the movement delta - only needed for mouse control or controller with pan enabled.
int nDeltaX = 0;
int nDeltaY = 0;
if ( !ASWInput()->ControllerModeActive() || joy_pan_camera.GetBool() )
{
nDeltaX = nMouseX - nCenterX;
nDeltaY = nMouseY - nCenterY;
// Calculate the camera shift and move the camera.
float flShiftX, flShiftY;
CalculateCameraShift( pPlayer, (float) nDeltaX / ( nCenterX * 2.0f ), (float) nDeltaY / ( nCenterY * 2.0f ), flShiftX, flShiftY );
VectorMA( vecCameraLocation, flShiftX, vecCamRight, vecCameraLocation );
vecCamUp.z = 0; // don't want the camera changing z
vecCamUp.NormalizeInPlace();
VectorMA( vecCameraLocation, -flShiftY, vecCamUp, vecCameraLocation );
}
bool bDeathcam = ASWGameRules() && ( ASWGameRules()->GetMarineDeathCamInterp() > 0.0f );
// Smooth the camera movement.
if ( bApplySmoothing && !bDeathcam )
{
SmoothCamera( pPlayer, vecCameraLocation );
pPlayer->m_vecLastCameraPosition = vecCameraLocation;
}
// Update the player camera data.
pPlayer->m_nLastCameraFrame = gpGlobals->framecount;
pPlayer->m_angLastCamera = angCamera;
// Do we still need this???
pPlayer->m_hLastMarine = pPlayer->GetMarine();
}
/*
==============================
CAM_StartMouseMove
==============================
*/
void CASWInput::CAM_StartMouseMove(void)
{
GetPerUser().m_fCameraMovingWithMouse=false;
GetPerUser().m_fCameraInterceptingMouse=false;
}
/*
==============================
CAM_StartDistance
routines to start the process of moving the cam in or out
using the mouse
==============================
*/
void CASWInput::CAM_StartDistance(void)
{
// asw
GetPerUser().m_fCameraDistanceMove=false;
GetPerUser().m_fCameraMovingWithMouse=false;
GetPerUser().m_fCameraInterceptingMouse=false;
}
/*
==============================
Init_Camera
==============================
*/
void CASWInput::Init_Camera( void )
{
for ( int i = 0; i < MAX_SPLITSCREEN_PLAYERS; ++i )
{
m_PerUser[ i ].m_fCameraInThirdPerson = true;
m_PerUser[ i ].m_CameraIsOrthographic = false;
// TODO: make this part of the per user data
m_fCurrentCameraPitch = false;
m_flCurrentCameraDist = asw_cam_marine_dist.GetFloat();
m_vecCameraVelocity.Init();
m_fShiftFraction = 1.0f;
m_bCameraFixed = false;
}
}
// asw - sets us up for moving the camera around in demos
void ASWDemoCamera_f()
{
if (!engine->IsPlayingDemo())
return;
engine->ClientCmd("firstperson");
engine->ClientCmd("asw_hl2_camera 1");
engine->ClientCmd("asw_controls 0");
}
ConCommand asw_demo_camera("asw_demo_camera", ASWDemoCamera_f);