diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/server/hl2/vehicle_cannon.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/server/hl2/vehicle_cannon.cpp')
| -rw-r--r-- | game/server/hl2/vehicle_cannon.cpp | 749 |
1 files changed, 749 insertions, 0 deletions
diff --git a/game/server/hl2/vehicle_cannon.cpp b/game/server/hl2/vehicle_cannon.cpp new file mode 100644 index 0000000..4316802 --- /dev/null +++ b/game/server/hl2/vehicle_cannon.cpp @@ -0,0 +1,749 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "cbase.h" +#include "vehicle_base.h" +#include "engine/IEngineSound.h" +#include "in_buttons.h" +#include "soundenvelope.h" +#include "soundent.h" +#include "physics_saverestore.h" +#include "vphysics/constraints.h" +#include "vcollide_parse.h" +#include "ndebugoverlay.h" +#include "npc_vehicledriver.h" +#include "hl2_player.h" +#include "explode.h" +#include "particle_smokegrenade.h" +#include "te_effect_dispatch.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +class CPropCannon; + +// Crane bones that have physics followers +static const char *pCannonFollowerBoneNames[] = +{ + "base", + "arm", + "platform", +}; + +#define CANNON_EXTENSION_RATE_MAX 0.01 +#define CANNON_TURN_RATE_MAX 1.2 + +#define MAX_CANNON_FLAT_REACH 1400.0 +#define MIN_CANNON_FLAT_REACH 700.0 +#define CANNON_EXTENSION_ACCEL 0.006 +#define CANNON_EXTENSION_DECEL 0.02 +#define CANNON_TURN_ACCEL 0.2 +#define CANNON_DECEL 0.5 + +#define CANNON_SLOWRAISE_TIME 5.0 + +#define CANNON_PROJECTILE_MODEL "models/props_combine/headcrabcannister01a.mdl" + +ConVar g_cannon_reloadtime( "g_cannon_reloadtime", "3", FCVAR_CHEAT | FCVAR_GAMEDLL ); +ConVar g_cannon_max_traveltime( "g_cannon_max_traveltime", "1.5", FCVAR_CHEAT | FCVAR_GAMEDLL ); +ConVar g_cannon_debug( "g_cannon_debug", "0", FCVAR_CHEAT | FCVAR_GAMEDLL ); +ConVar g_cannon_damageandradius( "g_cannon_damageandradius", "512", FCVAR_CHEAT | FCVAR_GAMEDLL ); + +// Turning stats +enum +{ + CANNON_TURNING_NOT, + CANNON_TURNING_LEFT, + CANNON_TURNING_RIGHT, +}; + +//----------------------------------------------------------------------------- +// Purpose: Crane vehicle server +//----------------------------------------------------------------------------- +class CCannonServerVehicle : public CBaseServerVehicle +{ + typedef CBaseServerVehicle BaseClass; +// IServerVehicle +public: + void GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV = NULL ); + + +protected: + CPropCannon *GetCannon( void ); +}; + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +class CPropCannon : public CBaseProp, public IDrivableVehicle +{ + DECLARE_CLASS( CPropCannon, CBaseProp ); +public: + DECLARE_DATADESC(); + DECLARE_SERVERCLASS(); + + CPropCannon( void ) + { + m_ServerVehicle.SetVehicle( this ); + } + + //IDrivableVehicle's Pure Virtuals + virtual CBaseEntity *GetDriver( void ); + virtual void ItemPostFrame( CBasePlayer *pPlayer ); + virtual void SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ); + virtual void ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData ) { return; } + virtual void FinishMove( CBasePlayer *player, CUserCmd *ucmd, CMoveData *move ) { return; } + virtual bool CanEnterVehicle( CBaseEntity *pEntity ); + virtual bool CanExitVehicle( CBaseEntity *pEntity ); + virtual void SetVehicleEntryAnim( bool bOn ) { m_bEnterAnimOn = bOn; } + virtual void SetVehicleExitAnim( bool bOn, Vector vecEyeExitEndpoint ) { m_bExitAnimOn = bOn; if ( bOn ) m_vecEyeExitEndpoint = vecEyeExitEndpoint; } + virtual void EnterVehicle( CBaseCombatCharacter *pPassenger ); + virtual bool AllowBlockedExit( CBaseCombatCharacter *pPassenger, int nRole ) { return true; } + virtual bool AllowMidairExit( CBaseCombatCharacter *pPassenger, int nRole ) { return false; } + virtual void PreExitVehicle( CBaseCombatCharacter *pPassenger, int nRole ) {} + virtual void ExitVehicle( int nRole ); + virtual string_t GetVehicleScriptName() { return m_vehicleScript; } + virtual bool PassengerShouldReceiveDamage( CTakeDamageInfo &info ) { return false; } + + // If this is a vehicle, returns the vehicle interface + virtual IServerVehicle *GetServerVehicle() { return &m_ServerVehicle; } + + virtual void Precache( void ); + virtual void Spawn( void ); + virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() | FCAP_IMPULSE_USE; }; + virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); + virtual void Think( void ); + + virtual bool CreateVPhysics( void ); + virtual void UpdateOnRemove( void ); + + void DriveCannon( int iDriverButtons, int iButtonsPressed ); + void ResetUseKey( CBasePlayer *pPlayer ); + void InitCannonSpeeds( void ); + void RunCraneMovement( float flTime ); + void LaunchProjectile( void ); + void ProjectileExplosion( void ); + +private: + + string_t m_vehicleScript; + + // Entering / Exiting + bool m_bLocked; + + CNetworkVar( bool, m_bEnterAnimOn ); + CNetworkVar( bool, m_bExitAnimOn ); + CNetworkVector( m_vecEyeExitEndpoint ); + + CNetworkHandle( CBasePlayer, m_hPlayer ); + + COutputEvent m_playerOn; + COutputEvent m_playerOff; + + int m_iTurning; + float m_flTurn; + + // Crane arm extension / retraction + bool m_bExtending; + float m_flExtension; + float m_flExtensionRate; + + // Speeds + float m_flMaxExtensionSpeed; + float m_flMaxTurnSpeed; + float m_flExtensionAccel; + float m_flExtensionDecel; + float m_flTurnAccel; + float m_flTurnDecel; + + float m_flFlyTime; + Vector m_vCrashPoint; + + float m_flNextAttackTime; + +protected: + // Contained IServerVehicle + CCannonServerVehicle m_ServerVehicle; + + // Contained Bone Follower manager + CBoneFollowerManager m_BoneFollowerManager; +}; + +LINK_ENTITY_TO_CLASS( prop_vehicle_cannon, CPropCannon ); + +BEGIN_DATADESC( CPropCannon ) + DEFINE_KEYFIELD( m_vehicleScript, FIELD_STRING, "vehiclescript" ), + DEFINE_OUTPUT( m_playerOn, "PlayerOn" ), + DEFINE_OUTPUT( m_playerOff, "PlayerOff" ), + + DEFINE_EMBEDDED( m_BoneFollowerManager ), + + DEFINE_FIELD( m_iTurning, FIELD_INTEGER ), + DEFINE_FIELD( m_flTurn, FIELD_FLOAT ), + DEFINE_FIELD( m_hPlayer, FIELD_EHANDLE ), + + DEFINE_FIELD( m_bExtending, FIELD_BOOLEAN ), + DEFINE_FIELD( m_flExtension, FIELD_FLOAT ), + DEFINE_FIELD( m_flExtensionRate, FIELD_FLOAT ), + + DEFINE_FIELD( m_flMaxExtensionSpeed, FIELD_FLOAT ), + DEFINE_FIELD( m_flMaxTurnSpeed, FIELD_FLOAT ), + DEFINE_FIELD( m_flExtensionAccel, FIELD_FLOAT ), + DEFINE_FIELD( m_flExtensionDecel, FIELD_FLOAT ), + + DEFINE_FIELD( m_flTurnAccel, FIELD_FLOAT ), + DEFINE_FIELD( m_flTurnDecel, FIELD_FLOAT ), + + DEFINE_FIELD( m_flFlyTime, FIELD_TIME ), + DEFINE_FIELD( m_vCrashPoint, FIELD_POSITION_VECTOR ), + + DEFINE_FIELD( m_flNextAttackTime, FIELD_TIME ), + +END_DATADESC() + +IMPLEMENT_SERVERCLASS_ST(CPropCannon, DT_PropCannon) + SendPropEHandle(SENDINFO(m_hPlayer)), + SendPropBool(SENDINFO(m_bEnterAnimOn)), + SendPropBool(SENDINFO(m_bExitAnimOn)), + SendPropVector(SENDINFO(m_vecEyeExitEndpoint), -1, SPROP_COORD), +END_SEND_TABLE(); + +//------------------------------------------------ +// Precache +//------------------------------------------------ +void CPropCannon::Precache( void ) +{ + BaseClass::Precache(); + m_ServerVehicle.Initialize( STRING( m_vehicleScript ) ); + + PrecacheModel( CANNON_PROJECTILE_MODEL ); + + PrecacheScriptSound( "HeadcrabCanister.LaunchSound" ); + PrecacheScriptSound( "HeadcrabCanister.Explosion" ); + PrecacheScriptSound( "Weapon_Mortar.Incomming" ); +} + + +//------------------------------------------------ +// Spawn +//------------------------------------------------ +void CPropCannon::Spawn( void ) +{ + Precache(); + SetModel( STRING( GetModelName() ) ); + SetCollisionGroup( COLLISION_GROUP_VEHICLE ); + + BaseClass::Spawn(); + + SetSolid( SOLID_BBOX ); + AddSolidFlags( FSOLID_NOT_SOLID ); + SetMoveType( MOVETYPE_NOCLIP ); + + m_takedamage = DAMAGE_EVENTS_ONLY; + + m_takedamage = DAMAGE_EVENTS_ONLY; + m_flTurn = 0; + m_flExtension = 0; + + m_flFlyTime = 0.0f; + m_flNextAttackTime = gpGlobals->curtime; + + InitCannonSpeeds(); + + SetPoseParameter( "armextensionpose", m_flExtension ); + + CreateVPhysics(); + SetNextThink( gpGlobals->curtime ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPropCannon::InitCannonSpeeds( void ) +{ + m_flMaxExtensionSpeed = CANNON_EXTENSION_RATE_MAX * 2; + m_flMaxTurnSpeed = CANNON_TURN_RATE_MAX * 2; + m_flExtensionAccel = CANNON_EXTENSION_ACCEL * 2; + m_flExtensionDecel = CANNON_EXTENSION_DECEL * 2; + m_flTurnAccel = CANNON_TURN_ACCEL * 2; + m_flTurnDecel = CANNON_DECEL * 2; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CBaseEntity *CPropCannon::GetDriver( void ) +{ + return m_hPlayer; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPropCannon::EnterVehicle( CBaseCombatCharacter *pPassenger ) +{ + if ( pPassenger == NULL ) + return; + + CBasePlayer *pPlayer = ToBasePlayer( pPassenger ); + if ( pPlayer != NULL ) + { + // Remove any player who may be in the vehicle at the moment + if ( m_hPlayer ) + { + ExitVehicle( VEHICLE_ROLE_DRIVER ); + } + + m_hPlayer = pPlayer; + m_playerOn.FireOutput( pPlayer, this, 0 ); + + //m_ServerVehicle.SoundStart(); + } + else + { + // NPCs not supported yet - jdw + Assert( 0 ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPropCannon::ExitVehicle( int nRole ) +{ + CBasePlayer *pPlayer = m_hPlayer; + if ( !pPlayer ) + return; + + m_hPlayer = NULL; + ResetUseKey( pPlayer ); + m_playerOff.FireOutput( pPlayer, this, 0 ); + m_bEnterAnimOn = false; + + //m_ServerVehicle.SoundShutdown( 1.0 ); +} + +//----------------------------------------------------------------------------- +// Purpose: Return true of the player's allowed to enter / exit the vehicle +//----------------------------------------------------------------------------- +bool CPropCannon::CanEnterVehicle( CBaseEntity *pEntity ) +{ + // Prevent entering if the vehicle's being driven by an NPC + if ( GetDriver() && GetDriver() != pEntity ) + return false; + + // Prevent entering if the vehicle's locked + return ( !m_bLocked ); +} + +//----------------------------------------------------------------------------- +// Purpose: Return true of the player's allowed to enter / exit the vehicle +//----------------------------------------------------------------------------- +bool CPropCannon::CanExitVehicle( CBaseEntity *pEntity ) +{ + // Prevent exiting if the vehicle's locked, or rotating + // Adrian: Check also if I'm currently jumping in or out. + return ( !m_bLocked && (GetLocalAngularVelocity() == vec3_angle) && m_bExitAnimOn == false && m_bEnterAnimOn == false ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPropCannon::ResetUseKey( CBasePlayer *pPlayer ) +{ + pPlayer->m_afButtonPressed &= ~IN_USE; +} + +//----------------------------------------------------------------------------- +// Purpose: Pass player movement into the crane's driving system +//----------------------------------------------------------------------------- +void CPropCannon::SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) +{ + // If the player's entering/exiting the vehicle, prevent movement + if ( !m_bEnterAnimOn && !m_bExitAnimOn ) + { + DriveCannon( ucmd->buttons, player->m_afButtonPressed ); + } + + // Run the crane's movement + RunCraneMovement( gpGlobals->frametime ); +} + +//----------------------------------------------------------------------------- +// Purpose: Crane rotates around with +left and +right, and extends/retracts +// the cable with +forward and +back. +//----------------------------------------------------------------------------- +void CPropCannon::DriveCannon( int iDriverButtons, int iButtonsPressed ) +{ + bool bWasExtending = m_bExtending; + + // Handle rotation of the crane + if ( iDriverButtons & IN_MOVELEFT ) + { + // Try adding some randomness to make it feel shaky? + float flTurnAdd = m_flTurnAccel; + // If we're turning back on ourselves, use decel speed + if ( m_flTurn < 0 ) + { + flTurnAdd = MAX( flTurnAdd, m_flTurnDecel ); + } + + m_flTurn = UTIL_Approach( m_flMaxTurnSpeed, m_flTurn, flTurnAdd * gpGlobals->frametime ); + + m_iTurning = CANNON_TURNING_LEFT; + } + else if ( iDriverButtons & IN_MOVERIGHT ) + { + // Try adding some randomness to make it feel shaky? + float flTurnAdd = m_flTurnAccel; + // If we're turning back on ourselves, increase the rate + if ( m_flTurn > 0 ) + { + flTurnAdd = MAX( flTurnAdd, m_flTurnDecel ); + } + m_flTurn = UTIL_Approach( -m_flMaxTurnSpeed, m_flTurn, flTurnAdd * gpGlobals->frametime ); + + m_iTurning = CANNON_TURNING_RIGHT; + } + else + { + m_flTurn = UTIL_Approach( 0, m_flTurn, m_flTurnDecel * gpGlobals->frametime ); + m_iTurning = CANNON_TURNING_NOT; + } + + SetLocalAngularVelocity( QAngle(0,m_flTurn * 10,0) ); + + // Handle extension / retraction of the arm + if ( iDriverButtons & IN_FORWARD ) + { + m_flExtensionRate = UTIL_Approach( m_flMaxExtensionSpeed, m_flExtensionRate, m_flExtensionAccel * gpGlobals->frametime ); + m_bExtending = true; + } + else if ( iDriverButtons & IN_BACK ) + { + m_flExtensionRate = UTIL_Approach( -m_flMaxExtensionSpeed, m_flExtensionRate, m_flExtensionAccel * gpGlobals->frametime ); + m_bExtending = true; + } + else + { + m_flExtensionRate = UTIL_Approach( 0, m_flExtensionRate, m_flExtensionDecel * gpGlobals->frametime ); + m_bExtending = false; + } + + //Msg("Turn: %f\nExtensionRate: %f\n", m_flTurn, m_flExtensionRate ); + + //If we're holding down an attack button, update our state + if ( iButtonsPressed & (IN_ATTACK | IN_ATTACK2) ) + { + if ( m_flNextAttackTime <= gpGlobals->curtime ) + { + LaunchProjectile(); + } + } + + float flSpeedPercentage = clamp( fabs(m_flTurn) / m_flMaxTurnSpeed, 0, 1 ); + vbs_sound_update_t params; + params.Defaults(); + params.bThrottleDown = (m_iTurning != CANNON_TURNING_NOT); + params.flCurrentSpeedFraction = flSpeedPercentage; + params.flWorldSpaceSpeed = 0; + + m_ServerVehicle.SoundUpdate( params ); + + // Play sounds for arm extension / retraction + if ( m_bExtending && !bWasExtending ) + { + m_ServerVehicle.StopSound( VS_ENGINE2_STOP ); + m_ServerVehicle.PlaySound( VS_ENGINE2_START ); + } + else if ( !m_bExtending && bWasExtending ) + { + m_ServerVehicle.StopSound( VS_ENGINE2_START ); + m_ServerVehicle.PlaySound( VS_ENGINE2_STOP ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pPlayer - +// *pMoveData - +//----------------------------------------------------------------------------- +void CPropCannon::RunCraneMovement( float flTime ) +{ + if ( m_flExtensionRate ) + { + // Extend / Retract the crane + m_flExtension = clamp( m_flExtension + (m_flExtensionRate * 10 * flTime), 0, 2 ); + SetPoseParameter( "armextensionpose", m_flExtension ); + StudioFrameAdvance(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *player - +//----------------------------------------------------------------------------- +void CPropCannon::ItemPostFrame( CBasePlayer *player ) +{ + +} + +void CPropCannon::ProjectileExplosion( void ) +{ + ExplosionCreate( m_vCrashPoint, vec3_angle, NULL, 512, 512, false ); + + // do damage + CTakeDamageInfo info( this, this, g_cannon_damageandradius.GetInt(), DMG_BLAST ); + + info.SetDamagePosition( m_vCrashPoint ); + RadiusDamage( info, m_vCrashPoint, g_cannon_damageandradius.GetInt(), CLASS_NONE, NULL ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPropCannon::Think( void ) +{ + SetNextThink( gpGlobals->curtime + 0.1 ); + + if ( GetDriver() ) + { + BaseClass::Think(); + } + + if ( GetDriver() ) + { + BaseClass::Think(); + + // play enter animation + StudioFrameAdvance(); + + // If the enter or exit animation has finished, tell the server vehicle + if ( IsSequenceFinished() && (m_bExitAnimOn || m_bEnterAnimOn) ) + { + if ( m_bEnterAnimOn ) + { + // Finished entering, display the hint for using the crane + //UTIL_HudHintText( m_hPlayer, "#Valve_Hint_CraneKeys" ); + } + + GetServerVehicle()->HandleEntryExitFinish( m_bExitAnimOn, true ); + } + } + else + { + // Run the crane's movement + // RunCraneMovement( 0.1 ); + } + + // Update follower bones + m_BoneFollowerManager.UpdateBoneFollowers(this); + + if ( m_flFlyTime > 0.0f ) + { + if ( m_flFlyTime - 1.0f <= gpGlobals->curtime && m_flFlyTime - 0.8f > gpGlobals->curtime) + { + CPASAttenuationFilter filter( this ); + + EmitSound_t ep; + ep.m_nChannel = CHAN_STATIC; + ep.m_pSoundName = "Weapon_Mortar.Incomming"; + ep.m_flVolume = 255; + ep.m_SoundLevel = SNDLVL_180dB; + + EmitSound( filter, entindex(), ep ); + } + + if ( m_flFlyTime <= gpGlobals->curtime ) + { + if ( m_vCrashPoint != vec3_origin ) + { + ProjectileExplosion(); + } + + CEffectData data; + + data.m_vOrigin = m_vCrashPoint; + data.m_flScale = 512; + DispatchEffect( "ThumperDust", data ); + + m_flFlyTime = 0.0f; + } + } + +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPropCannon::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) +{ + CBasePlayer *pPlayer = ToBasePlayer( pActivator ); + if ( !pPlayer ) + return; + + ResetUseKey( pPlayer ); + + GetServerVehicle()->HandlePassengerEntry( pPlayer, (value>0) ); +} + +void CPropCannon::LaunchProjectile( void ) +{ + //ADRIANTODO: Come back to this once we get the right model and remove all the fix ups caused by temp content. + + Vector vTipPos, vTipForward, vTipRight, vUp; + + GetAttachment( "cable_tip", vTipPos, &vTipForward, &vTipRight, &vUp ); + + bool bCollided = false; + bool bInSky = false; + float gravity = -gpGlobals->frametime * 600; + Vector vOrigin = vTipPos; + Vector vVelocity = vTipRight * 2500; + + float flDistance = 0.0f; + + int iFailSafe = 0; + + while ( bCollided == false && iFailSafe < 100000 ) + { + Vector vOldOrigin = vOrigin; + vOrigin = vOrigin + vVelocity * gpGlobals->frametime; + + flDistance += (vOrigin - vOldOrigin).Length(); + + if ( g_cannon_debug.GetBool() == true ) + { + NDebugOverlay::Line( vOldOrigin, vOrigin, 0, 255, 0, true, 5 ); + } + + trace_t pm; + UTIL_TraceLine( vOldOrigin, vOrigin, MASK_SOLID, this, COLLISION_GROUP_NONE, &pm ); + + if ( pm.surface.flags & SURF_SKY || pm.allsolid == true ) + { + bInSky = true; + iFailSafe++; + } + else + { + bInSky = false; + } + + iFailSafe++; + + if ( pm.fraction != 1.0f && bInSky == false ) + { + bCollided = true; + vOrigin = pm.endpos; + + if ( g_cannon_debug.GetBool() == true ) + { + NDebugOverlay::Box( vOrigin, Vector( 256, 256, 256 ), Vector( -256, -256, -256 ), 255, 0, 0, 0, 5 ); + } + } + else + { + vVelocity[2] += gravity; + } + } + + float flTravelTime = flDistance / vVelocity.Length(); + + if ( flTravelTime > g_cannon_max_traveltime.GetFloat() ) + { + flTravelTime = g_cannon_max_traveltime.GetFloat(); + + if ( bCollided == false ) + { + vOrigin = vec3_origin; + } + } + + m_flFlyTime = gpGlobals->curtime + flTravelTime; + m_vCrashPoint = vOrigin; + + m_flNextAttackTime = gpGlobals->curtime + g_cannon_reloadtime.GetFloat(); + + EmitSound( "HeadcrabCanister.LaunchSound" ); + + UTIL_ScreenShake( GetDriver()->GetAbsOrigin(), 50.0, 150.0, 1.0, 750, SHAKE_START, true ); +} + +//======================================================================================================================================== +// CRANE VEHICLE SERVER VEHICLE +//======================================================================================================================================== +CPropCannon *CCannonServerVehicle::GetCannon( void ) +{ + return (CPropCannon*)GetDrivableVehicle(); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CPropCannon::CreateVPhysics( void ) +{ + BaseClass::CreateVPhysics(); + m_BoneFollowerManager.InitBoneFollowers( this, ARRAYSIZE(pCannonFollowerBoneNames), pCannonFollowerBoneNames ); + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPropCannon::UpdateOnRemove( void ) +{ + m_BoneFollowerManager.DestroyBoneFollowers(); + BaseClass::UpdateOnRemove(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCannonServerVehicle::GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV /*= NULL*/ ) +{ + Assert( nRole == VEHICLE_ROLE_DRIVER ); + CBasePlayer *pPlayer = ToBasePlayer( GetDrivableVehicle()->GetDriver() ); + Assert( pPlayer ); + + *pAbsAngles = pPlayer->EyeAngles(); // yuck. this is an in/out parameter. + + float flPitchFactor = 1.0; + matrix3x4_t vehicleEyePosToWorld; + Vector vehicleEyeOrigin; + QAngle vehicleEyeAngles; + GetCannon()->GetAttachment( "vehicle_driver_eyes", vehicleEyeOrigin, vehicleEyeAngles ); + AngleMatrix( vehicleEyeAngles, vehicleEyePosToWorld ); + + // Compute the relative rotation between the unperterbed eye attachment + the eye angles + matrix3x4_t cameraToWorld; + AngleMatrix( *pAbsAngles, cameraToWorld ); + + matrix3x4_t worldToEyePos; + MatrixInvert( vehicleEyePosToWorld, worldToEyePos ); + + matrix3x4_t vehicleCameraToEyePos; + ConcatTransforms( worldToEyePos, cameraToWorld, vehicleCameraToEyePos ); + + // Now perterb the attachment point + vehicleEyeAngles.x = RemapAngleRange( PITCH_CURVE_ZERO * flPitchFactor, PITCH_CURVE_LINEAR, vehicleEyeAngles.x ); + vehicleEyeAngles.z = RemapAngleRange( ROLL_CURVE_ZERO * flPitchFactor, ROLL_CURVE_LINEAR, vehicleEyeAngles.z ); + AngleMatrix( vehicleEyeAngles, vehicleEyeOrigin, vehicleEyePosToWorld ); + + // Now treat the relative eye angles as being relative to this new, perterbed view position... + matrix3x4_t newCameraToWorld; + ConcatTransforms( vehicleEyePosToWorld, vehicleCameraToEyePos, newCameraToWorld ); + + // output new view abs angles + MatrixAngles( newCameraToWorld, *pAbsAngles ); + + // UNDONE: *pOrigin would already be correct in single player if the HandleView() on the server ran after vphysics + MatrixGetColumn( newCameraToWorld, 3, *pAbsOrigin ); +} |