diff options
| author | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
|---|---|---|
| committer | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
| commit | 39ed87570bdb2f86969d4be821c94b722dc71179 (patch) | |
| tree | abc53757f75f40c80278e87650ea92808274aa59 /mp/src/game/server/hl2/vehicle_cannon.cpp | |
| download | source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip | |
First version of the SOurce SDK 2013
Diffstat (limited to 'mp/src/game/server/hl2/vehicle_cannon.cpp')
| -rw-r--r-- | mp/src/game/server/hl2/vehicle_cannon.cpp | 749 |
1 files changed, 749 insertions, 0 deletions
diff --git a/mp/src/game/server/hl2/vehicle_cannon.cpp b/mp/src/game/server/hl2/vehicle_cannon.cpp new file mode 100644 index 00000000..31e3245c --- /dev/null +++ b/mp/src/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 );
+}
|