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.
782 lines
19 KiB
782 lines
19 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "fx_dod_shared.h" |
|
#include "weapon_dodbipodgun.h" |
|
#include "dod_gamerules.h" |
|
#include "engine/IEngineSound.h" |
|
|
|
#ifndef CLIENT_DLL |
|
#include "ndebugoverlay.h" |
|
#endif |
|
|
|
IMPLEMENT_NETWORKCLASS_ALIASED( DODBipodWeapon, DT_BipodWeapon ) |
|
|
|
BEGIN_NETWORK_TABLE( CDODBipodWeapon, DT_BipodWeapon ) |
|
#ifdef CLIENT_DLL |
|
RecvPropBool( RECVINFO( m_bDeployed ) ), |
|
RecvPropInt( RECVINFO( m_iDeployedReloadModelIndex) ), |
|
#else |
|
SendPropBool( SENDINFO( m_bDeployed ) ), |
|
SendPropModelIndex( SENDINFO(m_iDeployedReloadModelIndex) ), |
|
#endif |
|
END_NETWORK_TABLE() |
|
|
|
#ifdef CLIENT_DLL |
|
BEGIN_PREDICTION_DATA( CDODBipodWeapon ) |
|
DEFINE_PRED_FIELD( m_bDeployed, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ) |
|
END_PREDICTION_DATA() |
|
#endif |
|
|
|
CDODBipodWeapon::CDODBipodWeapon() |
|
{ |
|
} |
|
|
|
void CDODBipodWeapon::Spawn() |
|
{ |
|
SetDeployed( false ); |
|
m_flNextDeployCheckTime = 0; |
|
|
|
m_iCurrentWorldModel = 0; |
|
|
|
m_iAltFireHint = HINT_USE_DEPLOY; |
|
|
|
BaseClass::Spawn(); |
|
} |
|
|
|
void CDODBipodWeapon::SetDeployed( bool bDeployed ) |
|
{ |
|
if ( bDeployed == false ) |
|
{ |
|
m_hDeployedOnEnt = NULL; |
|
m_DeployedEntOrigin = vec3_origin; |
|
m_flDeployedHeight = 0; |
|
|
|
#ifdef GAME_DLL |
|
CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() ); |
|
if ( pPlayer ) |
|
{ |
|
pPlayer->HandleDeployedMGKillCount( 0 ); // reset when we undeploy |
|
} |
|
#endif |
|
} |
|
|
|
m_bDeployed = bDeployed; |
|
} |
|
|
|
void CDODBipodWeapon::Precache( void ) |
|
{ |
|
// precache base first, it loads weapon scripts |
|
BaseClass::Precache(); |
|
|
|
const CDODWeaponInfo &info = GetDODWpnData(); |
|
|
|
if( Q_strlen(info.m_szDeployedModel) > 0 ) |
|
{ |
|
Assert( info.m_iAltWpnCriteria & ALTWPN_CRITERIA_DEPLOYED ); |
|
m_iDeployedModelIndex = CBaseEntity::PrecacheModel( info.m_szDeployedModel ); |
|
} |
|
|
|
if( Q_strlen(info.m_szDeployedReloadModel) > 0 ) |
|
{ |
|
Assert( info.m_iAltWpnCriteria & ALTWPN_CRITERIA_DEPLOYED_RELOAD ); |
|
m_iDeployedReloadModelIndex = CBaseEntity::PrecacheModel( info.m_szDeployedReloadModel ); |
|
} |
|
|
|
if( Q_strlen(info.m_szProneDeployedReloadModel) > 0 ) |
|
{ |
|
Assert( info.m_iAltWpnCriteria & ALTWPN_CRITERIA_PRONE_DEPLOYED_RELOAD ); |
|
m_iProneDeployedReloadModelIndex = CBaseEntity::PrecacheModel( info.m_szProneDeployedReloadModel ); |
|
} |
|
|
|
m_iCurrentWorldModel = m_iWorldModelIndex; |
|
Assert( m_iCurrentWorldModel != 0 ); |
|
} |
|
|
|
bool CDODBipodWeapon::CanDrop( void ) |
|
{ |
|
return ( IsDeployed() == false ); |
|
} |
|
|
|
bool CDODBipodWeapon::CanHolster( void ) |
|
{ |
|
return ( IsDeployed() == false ); |
|
} |
|
|
|
void CDODBipodWeapon::Drop( const Vector &vecVelocity ) |
|
{ |
|
// If a player is killed while deployed, this resets the weapon state |
|
SetDeployed( false ); |
|
|
|
BaseClass::Drop( vecVelocity ); |
|
} |
|
|
|
void CDODBipodWeapon::SecondaryAttack( void ) |
|
{ |
|
// Toggle deployed / undeployed |
|
|
|
if ( IsDeployed() ) |
|
UndeployBipod(); |
|
else |
|
{ |
|
if ( CanAttack() ) |
|
{ |
|
bool bSuccess = AttemptToDeploy(); |
|
|
|
CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() ); |
|
Assert( pPlayer ); |
|
|
|
if ( !bSuccess ) |
|
{ |
|
pPlayer->HintMessage( HINT_MG_DEPLOY_USAGE ); |
|
} |
|
else |
|
{ |
|
#ifndef CLIENT_DLL |
|
pPlayer->RemoveHintTimer( m_iAltFireHint ); |
|
#endif |
|
} |
|
} |
|
} |
|
} |
|
|
|
bool CDODBipodWeapon::Reload( void ) |
|
{ |
|
bool bSuccess = BaseClass::Reload(); |
|
|
|
if ( bSuccess ) |
|
{ |
|
m_flNextSecondaryAttack = gpGlobals->curtime; |
|
} |
|
|
|
return bSuccess; |
|
} |
|
|
|
#include "in_buttons.h" |
|
// check in busy frame too, to catch cancelling reloads |
|
void CDODBipodWeapon::ItemBusyFrame( void ) |
|
{ |
|
BipodThink(); |
|
|
|
CBasePlayer *pPlayer = GetPlayerOwner(); |
|
|
|
if ( !pPlayer ) |
|
return; |
|
|
|
if ((pPlayer->m_nButtons & IN_ATTACK2) && (m_flNextSecondaryAttack <= gpGlobals->curtime)) |
|
{ |
|
SecondaryAttack(); |
|
|
|
pPlayer->m_nButtons &= ~IN_ATTACK2; |
|
} |
|
|
|
BaseClass::ItemBusyFrame(); |
|
} |
|
|
|
void CDODBipodWeapon::ItemPostFrame( void ) |
|
{ |
|
BipodThink(); |
|
BaseClass::ItemPostFrame(); |
|
} |
|
|
|
// see if we're still deployed on the same entity at the same height |
|
// in future can be expanded to check when deploying on other ents that may move / die / break |
|
void CDODBipodWeapon::BipodThink( void ) |
|
{ |
|
if ( m_flNextDeployCheckTime < gpGlobals->curtime ) |
|
{ |
|
if ( IsDeployed() ) |
|
{ |
|
if ( CheckDeployEnt() == false ) |
|
{ |
|
UndeployBipod(); |
|
|
|
// cancel any reload in progress |
|
m_bInReload = false; |
|
m_flNextPrimaryAttack = gpGlobals->curtime + 0.1; |
|
m_flNextSecondaryAttack = gpGlobals->curtime + 0.1; |
|
} |
|
} |
|
|
|
m_flNextDeployCheckTime = gpGlobals->curtime + 0.2; |
|
} |
|
} |
|
|
|
void CDODBipodWeapon::DoFireEffects() |
|
{ |
|
BaseClass::DoFireEffects(); |
|
|
|
CBaseEntity *pDeployedOn = m_hDeployedOnEnt.Get(); |
|
|
|
// in future can be expanded to check when deploying on other ents that may move / die / break |
|
if ( pDeployedOn && pDeployedOn->IsPlayer() && IsDeployed() ) |
|
{ |
|
#ifndef CLIENT_DLL |
|
CSingleUserRecipientFilter user( (CBasePlayer *)pDeployedOn ); |
|
enginesound->SetPlayerDSP( user, 32, false ); |
|
#endif |
|
} |
|
} |
|
|
|
// Do the work of deploying the gun at the current location and angles |
|
void CDODBipodWeapon::DeployBipod( float flHeight, CBaseEntity *pDeployedOn, float flYawLimitLeft, float flYawLimitRight ) |
|
{ |
|
m_flDeployedHeight = flHeight; |
|
m_hDeployedOnEnt = pDeployedOn; |
|
|
|
if ( pDeployedOn ) |
|
m_DeployedEntOrigin = pDeployedOn->GetAbsOrigin(); |
|
else |
|
m_DeployedEntOrigin = vec3_origin; // world ent |
|
|
|
SendWeaponAnim( GetDeployActivity() ); |
|
SetDeployed( true ); |
|
|
|
CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() ); |
|
pPlayer->m_Shared.SetDeployed( true, flHeight ); |
|
pPlayer->m_Shared.SetDeployedYawLimits( flYawLimitLeft, flYawLimitRight ); |
|
|
|
// Save this off so we do duck checks later, even though we won't be flagged as ducking |
|
m_bDuckedWhenDeployed = pPlayer->m_Shared.IsDucking(); |
|
|
|
// More TODO: |
|
// recalc our yaw limits if the item we're deployed on has moved or rotated |
|
// if our new limits are outside our current eye angles, undeploy us |
|
|
|
m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); |
|
m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration(); |
|
m_flTimeWeaponIdle = gpGlobals->curtime + SequenceDuration(); |
|
} |
|
|
|
// Do the work of undeploying the gun |
|
void CDODBipodWeapon::UndeployBipod( void ) |
|
{ |
|
SendWeaponAnim( GetUndeployActivity() ); |
|
SetDeployed( false ); |
|
|
|
CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() ); |
|
pPlayer->m_Shared.SetDeployed( false ); |
|
|
|
// if we cancelled our reload by undeploying, don't let the reload complete |
|
if ( m_bInReload ) |
|
m_bInReload = false; |
|
|
|
m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); |
|
m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration(); |
|
pPlayer->m_flNextAttack = m_flNextPrimaryAttack; |
|
m_flTimeWeaponIdle = gpGlobals->curtime + SequenceDuration(); |
|
} |
|
|
|
#ifndef CLIENT_DLL |
|
ConVar dod_debugmgdeploy( "dod_debugmgdeploy", "0", FCVAR_CHEAT|FCVAR_GAMEDLL ); |
|
#endif |
|
|
|
bool CDODBipodWeapon::AttemptToDeploy( void ) |
|
{ |
|
CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() ); |
|
|
|
if ( pPlayer->GetGroundEntity() == NULL ) |
|
return false; |
|
|
|
if ( pPlayer->m_Shared.IsGettingUpFromProne() || pPlayer->m_Shared.IsGoingProne() ) |
|
return false; |
|
|
|
CBaseEntity *pDeployedOn = NULL; |
|
float flDeployedHeight = 0.0f; |
|
float flYawLimitLeft = 0; |
|
float flYawLimitRight = 0; |
|
|
|
if ( TestDeploy( &flDeployedHeight, &pDeployedOn, &flYawLimitLeft, &flYawLimitRight ) ) |
|
{ |
|
if ( pPlayer->m_Shared.IsProne() && !pPlayer->m_Shared.IsGettingUpFromProne() ) |
|
{ |
|
DeployBipod( flDeployedHeight, NULL, flYawLimitLeft, flYawLimitRight ); |
|
return true; |
|
} |
|
else |
|
{ |
|
float flMinDeployHeight = 24.0; |
|
if( flDeployedHeight >= flMinDeployHeight ) |
|
{ |
|
DeployBipod( flDeployedHeight, pDeployedOn, flYawLimitLeft, flYawLimitRight ); |
|
return true; |
|
} |
|
} |
|
} |
|
|
|
return false; |
|
} |
|
|
|
bool CDODBipodWeapon::CheckDeployEnt( void ) |
|
{ |
|
CBaseEntity *pDeployedOn = NULL; |
|
float flDeployedHeight = 0.0f; |
|
|
|
if ( TestDeploy( &flDeployedHeight, &pDeployedOn ) == false ) |
|
return false; |
|
|
|
// If the entity we were deployed on has changed, or has moved, the origin |
|
// of it will be different. If so, recalc our yaw limits. |
|
if ( pDeployedOn ) |
|
{ |
|
if ( m_DeployedEntOrigin != pDeployedOn->GetAbsOrigin() ) |
|
{ |
|
float flYawLimitLeft = 0, flYawLimitRight = 0; |
|
TestDeploy( &flDeployedHeight, &pDeployedOn, &flYawLimitLeft, &flYawLimitRight ); |
|
|
|
CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() ); |
|
|
|
if ( pPlayer ) |
|
pPlayer->m_Shared.SetDeployedYawLimits( flYawLimitLeft, flYawLimitRight ); |
|
|
|
m_DeployedEntOrigin = pDeployedOn->GetAbsOrigin(); |
|
} |
|
} |
|
|
|
// 20 unit tolerance in height |
|
if ( abs( m_flDeployedHeight - flDeployedHeight ) > 20 ) |
|
return false; |
|
|
|
return true; |
|
} |
|
|
|
bool CDODBipodWeapon::TestDeploy( float *flDeployedHeight, CBaseEntity **pDeployedOn, float *flYawLimitLeft /* = NULL */, float *flYawLimitRight /* = NULL */ ) |
|
{ |
|
CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() ); |
|
|
|
QAngle angles = pPlayer->EyeAngles(); |
|
|
|
float flPitch = angles[PITCH]; |
|
if( flPitch > 180 ) |
|
{ |
|
flPitch -= 360; |
|
} |
|
|
|
if( flPitch > MIN_DEPLOY_PITCH || flPitch < MAX_DEPLOY_PITCH ) |
|
{ |
|
return false; |
|
} |
|
|
|
bool bSuccess = false; |
|
|
|
// if we're not finding the range, test at the current angles |
|
if ( flYawLimitLeft == NULL && flYawLimitRight == NULL ) |
|
{ |
|
// test our current angle only |
|
bSuccess = TestDeployAngle( pPlayer, flDeployedHeight, pDeployedOn, angles ); |
|
} |
|
else |
|
{ |
|
float flSaveYaw = angles[YAW]; |
|
|
|
const float flAngleDelta = 5; |
|
const float flMaxYaw = 45; |
|
|
|
float flLeft = 0; |
|
float flRight = 0; |
|
|
|
float flTestDeployHeight = 0; |
|
CBaseEntity *pTestDeployedOn = NULL; |
|
|
|
// Sweep Left |
|
while ( flLeft <= flMaxYaw ) |
|
{ |
|
angles[YAW] = flSaveYaw + flLeft; |
|
|
|
if ( TestDeployAngle( pPlayer, &flTestDeployHeight, &pTestDeployedOn, angles ) == true ) |
|
{ |
|
if ( flLeft == 0 ) // first sweep is authoritative on deploy height and entity |
|
{ |
|
*flDeployedHeight = flTestDeployHeight; |
|
*pDeployedOn = pTestDeployedOn; |
|
} |
|
else if ( abs( *flDeployedHeight - flTestDeployHeight ) > 20 ) |
|
{ |
|
// don't allow yaw to a position that is too different in height |
|
break; |
|
} |
|
|
|
*flYawLimitLeft = flLeft; |
|
} |
|
else |
|
{ |
|
break; |
|
} |
|
flLeft += flAngleDelta; |
|
} |
|
|
|
// can't deploy here, drop out early |
|
if ( flLeft <= 0 ) |
|
return false; |
|
|
|
// we already tested directly ahead and it was clear. skip one test |
|
flRight += flAngleDelta; |
|
|
|
// Sweep Right |
|
while ( flRight <= flMaxYaw ) |
|
{ |
|
angles[YAW] = flSaveYaw - flRight; |
|
|
|
if ( TestDeployAngle( pPlayer, &flTestDeployHeight, &pTestDeployedOn, angles ) == true ) |
|
{ |
|
if ( abs( *flDeployedHeight - flTestDeployHeight ) > 20 ) |
|
{ |
|
// don't allow yaw to a position that is too different in height |
|
break; |
|
} |
|
|
|
*flYawLimitRight = flRight; |
|
} |
|
else |
|
{ |
|
break; |
|
} |
|
flRight += flAngleDelta; |
|
} |
|
|
|
bSuccess = true; |
|
} |
|
|
|
return bSuccess; |
|
} |
|
|
|
//ConVar dod_deploy_box_size( "dod_deploy_box_size", "8", FCVAR_REPLICATED ); |
|
|
|
#include "util_shared.h" |
|
|
|
// trace filter that ignores all players except the passed one |
|
class CTraceFilterIgnorePlayersExceptFor : public CTraceFilterSimple |
|
{ |
|
public: |
|
// It does have a base, but we'll never network anything below here.. |
|
DECLARE_CLASS( CTraceFilterIgnorePlayersExceptFor, CTraceFilterSimple ); |
|
|
|
CTraceFilterIgnorePlayersExceptFor( const IHandleEntity *passentity, int collisionGroup ) |
|
: CTraceFilterSimple( passentity, collisionGroup ) |
|
{ |
|
} |
|
|
|
virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask ) |
|
{ |
|
CBaseEntity *pEntity = EntityFromEntityHandle( pServerEntity ); |
|
|
|
if ( pEntity->IsPlayer() ) |
|
{ |
|
if ( pEntity != GetPassEntity() ) |
|
{ |
|
return false; |
|
} |
|
else |
|
return true; |
|
} |
|
|
|
return true; |
|
} |
|
}; |
|
|
|
#define DEPLOY_DOWNTRACE_FORWARD_DIST 16 |
|
#define DEPLOY_DOWNTRACE_OFFSET 16 // yay for magic numbers |
|
|
|
bool CDODBipodWeapon::TestDeployAngle( CDODPlayer *pPlayer, float *flDeployedHeight, CBaseEntity **pDeployedOn, QAngle angles ) |
|
{ |
|
// make sure we are deployed on the same entity at the same height |
|
trace_t tr; |
|
|
|
angles[PITCH] = 0; |
|
|
|
Vector forward, right, up; |
|
AngleVectors( angles, &forward, &right, &up ); |
|
|
|
// start at top of player bbox |
|
Vector vecStart = pPlayer->GetAbsOrigin(); |
|
|
|
float flForwardTraceDist = 32; |
|
|
|
// check us as ducking if we are ducked, or if were ducked when we were deployed |
|
bool bDucking = pPlayer->m_Shared.IsDucking() || ( IsDeployed() && m_bDuckedWhenDeployed ); |
|
|
|
if ( pPlayer->m_Shared.IsProne() ) |
|
{ |
|
vecStart.z += VEC_PRONE_HULL_MAX[2]; |
|
flForwardTraceDist = 16; |
|
} |
|
else if ( bDucking ) |
|
{ |
|
vecStart.z += VEC_DUCK_HULL_MAX[2]; |
|
} |
|
else |
|
{ |
|
vecStart.z += 60; |
|
} |
|
|
|
int dim = 1; // dod_deploy_box_size.GetInt(); |
|
Vector vecDeployTraceBoxSize( dim, dim, dim ); |
|
|
|
vecStart.z -= vecDeployTraceBoxSize[2]; |
|
vecStart.z -= 4; |
|
|
|
// sandbags are around 50 units high. Shouldn't be able to deploy on anything a lot higher than that |
|
|
|
// optimal standing height ( for animation's sake ) is around 42 units |
|
// optimal ducking height is around 20 units ( 20 unit high object, plus 8 units of gun ) |
|
|
|
// Start one half box width away from the edge of the player hull |
|
Vector vecForwardStart = vecStart + forward * ( VEC_HULL_MAX_SCALED( pPlayer )[0] + vecDeployTraceBoxSize[0] ); |
|
|
|
int traceMask = MASK_SOLID; |
|
|
|
CBaseEntity *pDeployedOnPlayer = NULL; |
|
|
|
if ( m_hDeployedOnEnt && m_hDeployedOnEnt->IsPlayer() ) |
|
{ |
|
pDeployedOnPlayer = m_hDeployedOnEnt.Get(); |
|
} |
|
|
|
CTraceFilterIgnorePlayersExceptFor deployedFilter( pDeployedOnPlayer, COLLISION_GROUP_NONE ); |
|
CTraceFilterSimple undeployedFilter( pPlayer, COLLISION_GROUP_NONE ); |
|
|
|
// if we're deployed, skip all players except for the deployed on player |
|
// if we're not, only skip ourselves |
|
ITraceFilter *filter; |
|
if ( IsDeployed() ) |
|
filter = &deployedFilter; |
|
else |
|
filter = &undeployedFilter; |
|
|
|
UTIL_TraceHull( vecForwardStart, |
|
vecForwardStart + forward * ( flForwardTraceDist - 2 * vecDeployTraceBoxSize[0] ), |
|
-vecDeployTraceBoxSize, |
|
vecDeployTraceBoxSize, |
|
traceMask, |
|
filter, |
|
&tr ); |
|
|
|
#ifndef CLIENT_DLL |
|
if ( dod_debugmgdeploy.GetBool() ) |
|
{ |
|
NDebugOverlay::Line( vecForwardStart, vecForwardStart + forward * ( flForwardTraceDist - 2 * vecDeployTraceBoxSize[0] ), 0, 0, 255, true, 0.1 ); |
|
NDebugOverlay::Box( vecForwardStart, -vecDeployTraceBoxSize, vecDeployTraceBoxSize, 255, 0, 0, 128, 0.1 ); |
|
NDebugOverlay::Box( tr.endpos, -vecDeployTraceBoxSize, vecDeployTraceBoxSize, 0, 0, 255, 128, 0.1 ); |
|
} |
|
#endif |
|
|
|
// Test forward, are we trying to deploy into a solid object? |
|
if ( tr.fraction < 1.0 ) |
|
{ |
|
return false; |
|
} |
|
|
|
// If we're prone, we can always deploy, don't do the ground test |
|
if ( pPlayer->m_Shared.IsProne() && !pPlayer->m_Shared.IsGettingUpFromProne() ) |
|
{ |
|
// MATTTODO: do trace from *front* of player, not from the edge of crouch hull |
|
// this is sufficient |
|
*flDeployedHeight = PRONE_DEPLOY_HEIGHT; |
|
return true; |
|
} |
|
|
|
// fix prediction hitch when coming up from prone. client thinks we aren't |
|
// prone, but hull is still prone hull |
|
// assumes prone hull is shorter than duck hull! |
|
if ( pPlayer->WorldAlignMaxs().z <= VEC_PRONE_HULL_MAX.z ) |
|
return false; |
|
|
|
// Else trace down |
|
Vector vecDownTraceStart = vecStart + forward * ( VEC_HULL_MAX_SCALED( pPlayer )[0] + DEPLOY_DOWNTRACE_FORWARD_DIST ); |
|
int iTraceHeight = -( pPlayer->WorldAlignMaxs().z ); |
|
|
|
|
|
// search down from the forward trace |
|
// use the farthest point first. If that fails, move towards the player a few times |
|
// to see if they are trying to deploy on a thin railing |
|
|
|
bool bFound = false; |
|
|
|
int maxAttempts = 4; |
|
float flHighestTraceEnd = vecDownTraceStart.z + iTraceHeight; |
|
CBaseEntity *pBestDeployEnt = NULL; |
|
|
|
while( maxAttempts > 0 ) |
|
{ |
|
UTIL_TraceHull( vecDownTraceStart, |
|
vecDownTraceStart + Vector(0,0,iTraceHeight), // trace forward one box width |
|
-vecDeployTraceBoxSize, |
|
vecDeployTraceBoxSize, |
|
traceMask, |
|
filter, |
|
&tr ); |
|
|
|
#ifndef CLIENT_DLL |
|
if ( dod_debugmgdeploy.GetBool() ) |
|
{ |
|
NDebugOverlay::Line( vecDownTraceStart, tr.endpos, 255, 0, 0, true, 0.1 ); |
|
NDebugOverlay::Box( vecDownTraceStart, -vecDeployTraceBoxSize, vecDeployTraceBoxSize, 255, 0, 0, 128, 0.1 ); |
|
NDebugOverlay::Box( tr.endpos, -vecDeployTraceBoxSize, vecDeployTraceBoxSize, 0, 0, 255, 128, 0.1 ); |
|
} |
|
#endif |
|
|
|
bool bSuccess = ( tr.fraction < 1.0 ) && !tr.startsolid && !tr.allsolid; |
|
|
|
// if this is the first one found, set found flag |
|
if ( bSuccess && !bFound ) |
|
{ |
|
bFound = true; |
|
} |
|
else if ( bFound == true && bSuccess == false ) |
|
{ |
|
// it failed and we have some data. break here |
|
break; |
|
} |
|
|
|
// if this trace is better ( higher ) use this one |
|
if ( tr.endpos.z > flHighestTraceEnd ) |
|
{ |
|
flHighestTraceEnd = tr.endpos.z; |
|
pBestDeployEnt = tr.m_pEnt; |
|
} |
|
|
|
--maxAttempts; |
|
|
|
// move towards the player, looking for a better height to deploy on |
|
vecDownTraceStart += forward * -4; |
|
} |
|
|
|
if ( bFound == false || pBestDeployEnt == NULL ) |
|
return false; |
|
|
|
*pDeployedOn = pBestDeployEnt; |
|
*flDeployedHeight = flHighestTraceEnd - vecDeployTraceBoxSize[0] + DEPLOY_DOWNTRACE_OFFSET - pPlayer->GetAbsOrigin().z; |
|
return true; |
|
} |
|
|
|
Activity CDODBipodWeapon::GetUndeployActivity( void ) |
|
{ |
|
return ACT_VM_UNDEPLOY; |
|
} |
|
|
|
Activity CDODBipodWeapon::GetDeployActivity( void ) |
|
{ |
|
return ACT_VM_DEPLOY; |
|
} |
|
|
|
|
|
Activity CDODBipodWeapon::GetPrimaryAttackActivity( void ) |
|
{ |
|
Activity actPrim; |
|
|
|
if( IsDeployed() ) |
|
actPrim = ACT_VM_PRIMARYATTACK_DEPLOYED; |
|
else |
|
actPrim = ACT_VM_PRIMARYATTACK; |
|
|
|
return actPrim; |
|
} |
|
|
|
Activity CDODBipodWeapon::GetReloadActivity( void ) |
|
{ |
|
Activity actReload; |
|
|
|
if( IsDeployed() ) |
|
actReload = ACT_VM_RELOAD_DEPLOYED; |
|
else |
|
actReload = ACT_VM_RELOAD; |
|
|
|
return actReload; |
|
} |
|
|
|
Activity CDODBipodWeapon::GetIdleActivity( void ) |
|
{ |
|
Activity actIdle; |
|
|
|
if( IsDeployed() ) |
|
actIdle = ACT_VM_IDLE_DEPLOYED; |
|
else |
|
actIdle = ACT_VM_IDLE; |
|
|
|
return actIdle; |
|
} |
|
|
|
|
|
float CDODBipodWeapon::GetWeaponAccuracy( float flPlayerSpeed ) |
|
{ |
|
float flSpread = BaseClass::GetWeaponAccuracy( flPlayerSpeed ); |
|
|
|
if( IsDeployed() ) |
|
{ |
|
flSpread = m_pWeaponInfo->m_flSecondaryAccuracy; |
|
} |
|
|
|
return flSpread; |
|
} |
|
|
|
#ifdef CLIENT_DLL |
|
|
|
int CDODBipodWeapon::GetWorldModelIndex( void ) |
|
{ |
|
if( GetOwner() == NULL ) |
|
return m_iWorldModelIndex; |
|
else if( m_bUseAltWeaponModel ) |
|
return m_iWorldModelIndex; //override for hand signals etc |
|
else |
|
return m_iCurrentWorldModel; |
|
} |
|
|
|
void CDODBipodWeapon::CheckForAltWeapon( int iCurrentState ) |
|
{ |
|
int iCriteria = GetDODWpnData().m_iAltWpnCriteria; |
|
|
|
bool bReloading = ( iCurrentState & ALTWPN_CRITERIA_RELOADING ); |
|
|
|
if( bReloading ) |
|
{ |
|
if( IsDeployed() && iCurrentState & ALTWPN_CRITERIA_PRONE && |
|
iCriteria & ALTWPN_CRITERIA_PRONE_DEPLOYED_RELOAD ) |
|
{ |
|
m_iCurrentWorldModel = m_iProneDeployedReloadModelIndex; // prone deployed reload |
|
} |
|
else if( IsDeployed() && iCriteria & ALTWPN_CRITERIA_DEPLOYED_RELOAD ) |
|
{ |
|
m_iCurrentWorldModel = m_iDeployedReloadModelIndex; // deployed reload |
|
} |
|
else if( iCriteria & ALTWPN_CRITERIA_RELOADING ) |
|
{ |
|
m_iCurrentWorldModel = m_iReloadModelIndex; // left handed reload |
|
} |
|
else |
|
{ |
|
m_iCurrentWorldModel = m_iWorldModelIndex; // normal weapon reload |
|
} |
|
} |
|
else if( IsDeployed() && iCriteria & ALTWPN_CRITERIA_DEPLOYED ) |
|
{ |
|
m_iCurrentWorldModel = m_iDeployedModelIndex; // bipod down |
|
} |
|
else if( (iCurrentState & iCriteria) & ALTWPN_CRITERIA_FIRING ) |
|
{ |
|
// don't think we have any weapons that do this |
|
m_iCurrentWorldModel = m_iReloadModelIndex; // left handed shooting? |
|
} |
|
else |
|
{ |
|
m_iCurrentWorldModel = m_iWorldModelIndex; // normal weapon |
|
} |
|
} |
|
|
|
ConVar deployed_mg_sensitivity( "deployed_mg_sensitivity", "0.9", FCVAR_CHEAT, "Mouse sensitivity while deploying a machine gun" ); |
|
|
|
void CDODBipodWeapon::OverrideMouseInput( float *x, float *y ) |
|
{ |
|
if( IsDeployed() ) |
|
{ |
|
float flSensitivity = deployed_mg_sensitivity.GetFloat(); |
|
|
|
*x *= flSensitivity; |
|
*y *= flSensitivity; |
|
} |
|
} |
|
|
|
#endif
|
|
|