You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
749 lines
22 KiB
749 lines
22 KiB
//========= 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 ); |
|
}
|
|
|