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.
509 lines
15 KiB
509 lines
15 KiB
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
//=============================================================================//
|
|
|
|
#include "cbase.h"
|
|
#include "weapon_portalbasecombatweapon.h"
|
|
#include "in_buttons.h"
|
|
|
|
#include "portal_player_shared.h"
|
|
|
|
#if defined( CLIENT_DLL )
|
|
#include "c_portal_player.h"
|
|
#else
|
|
#include "vphysics/constraints.h"
|
|
#include "gameweaponmanager.h"
|
|
#endif
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
IMPLEMENT_NETWORKCLASS_ALIASED( BasePortalCombatWeapon , DT_BasePortalCombatWeapon )
|
|
LINK_ENTITY_TO_CLASS_ALIASED( baseportalcombatweapon, BasePortalCombatWeapon );
|
|
|
|
BEGIN_NETWORK_TABLE( CBasePortalCombatWeapon , DT_BasePortalCombatWeapon )
|
|
#if !defined( CLIENT_DLL )
|
|
// SendPropInt( SENDINFO( m_bReflectViewModelAnimations ), 1, SPROP_UNSIGNED ),
|
|
#else
|
|
// RecvPropInt( RECVINFO( m_bReflectViewModelAnimations ) ),
|
|
#endif
|
|
END_NETWORK_TABLE()
|
|
|
|
|
|
#if !defined( CLIENT_DLL )
|
|
|
|
#include "globalstate.h"
|
|
|
|
//---------------------------------------------------------
|
|
// Save/Restore
|
|
//---------------------------------------------------------
|
|
BEGIN_DATADESC( CBasePortalCombatWeapon )
|
|
|
|
DEFINE_FIELD( m_bLowered, FIELD_BOOLEAN ),
|
|
DEFINE_FIELD( m_flRaiseTime, FIELD_TIME ),
|
|
DEFINE_FIELD( m_flHolsterTime, FIELD_TIME ),
|
|
DEFINE_FIELD( m_flNextRepeatPrimaryAttack, FIELD_TIME ),
|
|
DEFINE_FIELD( m_flNextRepeatSecondaryAttack, FIELD_TIME ),
|
|
END_DATADESC()
|
|
|
|
#else
|
|
|
|
BEGIN_PREDICTION_DATA( CBasePortalCombatWeapon )
|
|
DEFINE_FIELD( m_flNextRepeatPrimaryAttack, FIELD_TIME ),
|
|
DEFINE_FIELD( m_flNextRepeatSecondaryAttack, FIELD_TIME ),
|
|
END_PREDICTION_DATA()
|
|
|
|
#endif
|
|
|
|
extern ConVar sk_auto_reload_time;
|
|
|
|
CBasePortalCombatWeapon::CBasePortalCombatWeapon( void )
|
|
{
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CBasePortalCombatWeapon::ItemHolsterFrame( void )
|
|
{
|
|
BaseClass::ItemHolsterFrame();
|
|
|
|
// Must be player held
|
|
if ( GetOwner() && GetOwner()->IsPlayer() == false )
|
|
return;
|
|
|
|
// We can't be active
|
|
if ( GetOwner()->GetActiveWeapon() == this )
|
|
return;
|
|
|
|
// If it's been longer than three seconds, reload
|
|
if ( ( gpGlobals->curtime - m_flHolsterTime ) > sk_auto_reload_time.GetFloat() )
|
|
{
|
|
// Just load the clip with no animations
|
|
FinishReload();
|
|
m_flHolsterTime = gpGlobals->curtime;
|
|
}
|
|
}
|
|
|
|
bool CBasePortalCombatWeapon::CanLower()
|
|
{
|
|
if ( SelectWeightedSequence( ACT_VM_IDLE_LOWERED ) == ACTIVITY_NOT_AVAILABLE )
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Drops the weapon into a lowered pose
|
|
// Output : Returns true on success, false on failure.
|
|
//-----------------------------------------------------------------------------
|
|
bool CBasePortalCombatWeapon::Lower( void )
|
|
{
|
|
//Don't bother if we don't have the animation
|
|
if ( SelectWeightedSequence( ACT_VM_IDLE_LOWERED ) == ACTIVITY_NOT_AVAILABLE )
|
|
return false;
|
|
|
|
m_bLowered = true;
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Brings the weapon up to the ready position
|
|
// Output : Returns true on success, false on failure.
|
|
//-----------------------------------------------------------------------------
|
|
bool CBasePortalCombatWeapon::Ready( void )
|
|
{
|
|
//Don't bother if we don't have the animation
|
|
if ( SelectWeightedSequence( ACT_VM_LOWERED_TO_IDLE ) == ACTIVITY_NOT_AVAILABLE )
|
|
return false;
|
|
|
|
m_bLowered = false;
|
|
m_flRaiseTime = gpGlobals->curtime + 0.5f;
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Output : Returns true on success, false on failure.
|
|
//-----------------------------------------------------------------------------
|
|
bool CBasePortalCombatWeapon::Deploy( void )
|
|
{
|
|
return BaseClass::Deploy();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Output : Returns true on success, false on failure.
|
|
//-----------------------------------------------------------------------------
|
|
bool CBasePortalCombatWeapon::Holster( CBaseCombatWeapon *pSwitchingTo )
|
|
{
|
|
if ( BaseClass::Holster( pSwitchingTo ) )
|
|
{
|
|
m_flHolsterTime = gpGlobals->curtime;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Output : Returns true on success, false on failure.
|
|
//-----------------------------------------------------------------------------
|
|
bool CBasePortalCombatWeapon::WeaponShouldBeLowered( void )
|
|
{
|
|
// Can't be in the middle of another animation
|
|
if ( GetIdealActivity() != ACT_VM_IDLE_LOWERED && GetIdealActivity() != ACT_VM_IDLE &&
|
|
GetIdealActivity() != ACT_VM_IDLE_TO_LOWERED && GetIdealActivity() != ACT_VM_LOWERED_TO_IDLE )
|
|
return false;
|
|
|
|
if ( m_bLowered )
|
|
return true;
|
|
|
|
#if !defined( CLIENT_DLL )
|
|
|
|
if ( GlobalEntity_GetState( "friendly_encounter" ) == GLOBAL_ON )
|
|
return true;
|
|
|
|
#endif
|
|
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Allows the weapon to choose proper weapon idle animation
|
|
//-----------------------------------------------------------------------------
|
|
void CBasePortalCombatWeapon::WeaponIdle( void )
|
|
{
|
|
}
|
|
|
|
#if defined( CLIENT_DLL )
|
|
|
|
extern float g_lateralBob;
|
|
extern float g_verticalBob;
|
|
|
|
#define HL2_BOB_CYCLE_MIN 1.0f
|
|
#define HL2_BOB_CYCLE_MAX 0.45f
|
|
#define HL2_BOB 0.002f
|
|
#define HL2_BOB_UP 0.5f
|
|
|
|
#if !defined( PORTAL2 )
|
|
static ConVar cl_bobcycle( "cl_bobcycle","0.8" );
|
|
static ConVar cl_bob( "cl_bob","0.002" );
|
|
static ConVar cl_bobup( "cl_bobup","0.5" );
|
|
|
|
// Register these cvars if needed for easy tweaking
|
|
static ConVar v_iyaw_cycle( "v_iyaw_cycle", "2", FCVAR_CHEAT );
|
|
static ConVar v_iroll_cycle( "v_iroll_cycle", "0.5", FCVAR_CHEAT );
|
|
static ConVar v_ipitch_cycle( "v_ipitch_cycle", "1", FCVAR_CHEAT );
|
|
static ConVar v_iyaw_level( "v_iyaw_level", "0.3", FCVAR_CHEAT );
|
|
static ConVar v_iroll_level( "v_iroll_level", "0.1", FCVAR_CHEAT );
|
|
static ConVar v_ipitch_level( "v_ipitch_level", "0.3", FCVAR_CHEAT );
|
|
#endif
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Output : float
|
|
//-----------------------------------------------------------------------------
|
|
float CBasePortalCombatWeapon::CalcViewmodelBob( void )
|
|
{
|
|
static float bobtime;
|
|
static float lastbobtime;
|
|
float cycle;
|
|
|
|
CBasePlayer *player = ToBasePlayer( GetOwner() );
|
|
//Assert( player );
|
|
|
|
//NOTENOTE: For now, let this cycle continue when in the air, because it snaps badly without it
|
|
|
|
if ( ( !gpGlobals->frametime ) || ( player == NULL ) )
|
|
{
|
|
//NOTENOTE: We don't use this return value in our case (need to restructure the calculation function setup!)
|
|
return 0.0f;// just use old value
|
|
}
|
|
|
|
// Note: we use paint code for this so when player move on speed paint, gun bob faster (Bank)
|
|
//Find the speed of the player
|
|
float speed = player->GetLocalVelocity().Length();
|
|
|
|
speed = clamp( speed, -player->MaxSpeed(), player->MaxSpeed() );
|
|
|
|
float bob_offset = RemapVal( speed, 0, player->MaxSpeed(), 0.0f, 1.0f );
|
|
|
|
////Find the speed of the player
|
|
//float speed = player->GetLocalVelocity().Length2D();
|
|
|
|
////FIXME: This maximum speed value must come from the server.
|
|
//// MaxSpeed() is not sufficient for dealing with sprinting - jdw
|
|
|
|
//speed = clamp( speed, -320, 320 );
|
|
|
|
//float bob_offset = RemapVal( speed, 0, 320, 0.0f, 1.0f );
|
|
|
|
bobtime += ( gpGlobals->curtime - lastbobtime ) * bob_offset;
|
|
lastbobtime = gpGlobals->curtime;
|
|
|
|
//Calculate the vertical bob
|
|
cycle = bobtime - (int)(bobtime/HL2_BOB_CYCLE_MAX)*HL2_BOB_CYCLE_MAX;
|
|
cycle /= HL2_BOB_CYCLE_MAX;
|
|
|
|
if ( cycle < HL2_BOB_UP )
|
|
{
|
|
cycle = M_PI * cycle / HL2_BOB_UP;
|
|
}
|
|
else
|
|
{
|
|
cycle = M_PI + M_PI*(cycle-HL2_BOB_UP)/(1.0 - HL2_BOB_UP);
|
|
}
|
|
|
|
g_verticalBob = speed*0.005f;
|
|
g_verticalBob = g_verticalBob*0.3 + g_verticalBob*0.7*sin(cycle);
|
|
|
|
g_verticalBob = clamp( g_verticalBob, -7.0f, 4.0f );
|
|
|
|
//Calculate the lateral bob
|
|
cycle = bobtime - (int)(bobtime/HL2_BOB_CYCLE_MAX*2)*HL2_BOB_CYCLE_MAX*2;
|
|
cycle /= HL2_BOB_CYCLE_MAX*2;
|
|
|
|
if ( cycle < HL2_BOB_UP )
|
|
{
|
|
cycle = M_PI * cycle / HL2_BOB_UP;
|
|
}
|
|
else
|
|
{
|
|
cycle = M_PI + M_PI*(cycle-HL2_BOB_UP)/(1.0 - HL2_BOB_UP);
|
|
}
|
|
|
|
g_lateralBob = speed*0.005f;
|
|
g_lateralBob = g_lateralBob*0.3 + g_lateralBob*0.7*sin(cycle);
|
|
g_lateralBob = clamp( g_lateralBob, -7.0f, 4.0f );
|
|
|
|
//NOTENOTE: We don't use this return value in our case (need to restructure the calculation function setup!)
|
|
return 0.0f;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : &origin -
|
|
// &angles -
|
|
// viewmodelindex -
|
|
//-----------------------------------------------------------------------------
|
|
void CBasePortalCombatWeapon::AddViewmodelBob( CBaseViewModel *viewmodel, Vector &origin, QAngle &angles )
|
|
{
|
|
Vector forward, right, up;
|
|
AngleVectors( angles, &forward, &right, &up );
|
|
|
|
CalcViewmodelBob();
|
|
|
|
|
|
// Note: we need to use paint code for gun bob so the gun bobs correctly when player sticks on walls (Bank)
|
|
C_Portal_Player *pPortalPlayer = ToPortalPlayer( GetOwner() );
|
|
if ( !pPortalPlayer )
|
|
return;
|
|
|
|
// Apply bob, but scaled down to 40%
|
|
VectorMA( origin, g_verticalBob * 0.1f, forward, origin );
|
|
|
|
// Z bob a bit more
|
|
origin += g_verticalBob * 0.1f * pPortalPlayer->GetPortalPlayerLocalData().m_Up;
|
|
|
|
//move left and right
|
|
VectorMA( origin, g_lateralBob * 0.8f, right, origin );
|
|
|
|
//roll, pitch, yaw
|
|
float rollAngle = g_verticalBob * 0.5f;
|
|
VMatrix rotMatrix;
|
|
Vector rotAxis = CrossProduct( right, up ).Normalized();
|
|
|
|
MatrixBuildRotationAboutAxis( rotMatrix, rotAxis, rollAngle );
|
|
up = rotMatrix * up;
|
|
forward = rotMatrix * forward;
|
|
right = rotMatrix * right;
|
|
|
|
float pitchAngle = -g_verticalBob * 0.4f;
|
|
rotAxis = right;
|
|
MatrixBuildRotationAboutAxis( rotMatrix, rotAxis, pitchAngle );
|
|
up = rotMatrix * up;
|
|
forward = rotMatrix * forward;
|
|
|
|
float yawAngle = -g_lateralBob * 0.3f;
|
|
rotAxis = up;
|
|
MatrixBuildRotationAboutAxis( rotMatrix, rotAxis, yawAngle );
|
|
forward = rotMatrix * forward;
|
|
|
|
VectorAngles( forward, up, angles );
|
|
|
|
//// Apply bob, but scaled down to 40%
|
|
//VectorMA( origin, g_verticalBob * 0.1f, forward, origin );
|
|
//
|
|
//// Z bob a bit more
|
|
//origin[2] += g_verticalBob * 0.1f;
|
|
//
|
|
//// bob the angles
|
|
//angles[ ROLL ] += g_verticalBob * 0.5f;
|
|
//angles[ PITCH ] -= g_verticalBob * 0.4f;
|
|
|
|
//angles[ YAW ] -= g_lateralBob * 0.3f;
|
|
|
|
//VectorMA( origin, g_lateralBob * 0.8f, right, origin );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
Vector CBasePortalCombatWeapon::GetBulletSpread( WeaponProficiency_t proficiency )
|
|
{
|
|
return BaseClass::GetBulletSpread( proficiency );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
float CBasePortalCombatWeapon::GetSpreadBias( WeaponProficiency_t proficiency )
|
|
{
|
|
return BaseClass::GetSpreadBias( proficiency );
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
|
|
const WeaponProficiencyInfo_t *CBasePortalCombatWeapon::GetProficiencyValues()
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
#else
|
|
|
|
// Server stubs
|
|
float CBasePortalCombatWeapon::CalcViewmodelBob( void )
|
|
{
|
|
return 0.0f;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : &origin -
|
|
// &angles -
|
|
// viewmodelindex -
|
|
//-----------------------------------------------------------------------------
|
|
void CBasePortalCombatWeapon::AddViewmodelBob( CBaseViewModel *viewmodel, Vector &origin, QAngle &angles )
|
|
{
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
Vector CBasePortalCombatWeapon::GetBulletSpread( WeaponProficiency_t proficiency )
|
|
{
|
|
Vector baseSpread = BaseClass::GetBulletSpread( proficiency );
|
|
|
|
const WeaponProficiencyInfo_t *pProficiencyValues = GetProficiencyValues();
|
|
float flModifier = (pProficiencyValues)[ proficiency ].spreadscale;
|
|
return ( baseSpread * flModifier );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
float CBasePortalCombatWeapon::GetSpreadBias( WeaponProficiency_t proficiency )
|
|
{
|
|
const WeaponProficiencyInfo_t *pProficiencyValues = GetProficiencyValues();
|
|
return (pProficiencyValues)[ proficiency ].bias;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
const WeaponProficiencyInfo_t *CBasePortalCombatWeapon::GetProficiencyValues()
|
|
{
|
|
return GetDefaultProficiencyValues();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
const WeaponProficiencyInfo_t *CBasePortalCombatWeapon::GetDefaultProficiencyValues()
|
|
{
|
|
// Weapon proficiency table. Keep this in sync with WeaponProficiency_t enum in the header!!
|
|
static WeaponProficiencyInfo_t g_BaseWeaponProficiencyTable[] =
|
|
{
|
|
{ 2.50, 1.0 },
|
|
{ 2.00, 1.0 },
|
|
{ 1.50, 1.0 },
|
|
{ 1.25, 1.0 },
|
|
{ 1.00, 1.0 },
|
|
};
|
|
|
|
COMPILE_TIME_ASSERT( ARRAYSIZE(g_BaseWeaponProficiencyTable) == WEAPON_PROFICIENCY_PERFECT + 1);
|
|
|
|
return g_BaseWeaponProficiencyTable;
|
|
}
|
|
|
|
#endif
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Handle firing
|
|
//-----------------------------------------------------------------------------
|
|
void CBasePortalCombatWeapon::ItemPostFrame( void )
|
|
{
|
|
CPortal_Player *pOwner = ToPortalPlayer( GetOwner() );
|
|
if ( pOwner == NULL )
|
|
return;
|
|
|
|
// Primary attack
|
|
if ( pOwner->m_nButtons & IN_ATTACK && ( m_flNextPrimaryAttack <= gpGlobals->curtime ) )
|
|
{
|
|
if ( pOwner->GetWaterLevel() == 3 && m_bFiresUnderwater == false )
|
|
{
|
|
// This weapon doesn't fire underwater
|
|
WeaponSound(EMPTY);
|
|
m_flNextPrimaryAttack = m_flNextSecondaryAttack = gpGlobals->curtime + 0.2;
|
|
return;
|
|
}
|
|
|
|
// If they're still holding down the button, wait for the next fire time
|
|
if ( ( pOwner->m_afButtonLast & IN_ATTACK ) && ( m_flNextRepeatPrimaryAttack > gpGlobals->curtime ) )
|
|
return;
|
|
|
|
PrimaryAttack();
|
|
return;
|
|
}
|
|
|
|
// Secondary attack
|
|
if ( pOwner->m_nButtons & IN_ATTACK2 && ( m_flNextSecondaryAttack <= gpGlobals->curtime ) )
|
|
{
|
|
if ( pOwner->GetWaterLevel() == 3 )
|
|
{
|
|
// This weapon doesn't fire underwater
|
|
WeaponSound( EMPTY );
|
|
m_flNextPrimaryAttack = m_flNextSecondaryAttack = gpGlobals->curtime + 0.2;
|
|
return;
|
|
}
|
|
|
|
// If they're still holding down the button, wait for the next fire time
|
|
if ( ( pOwner->m_afButtonLast & IN_ATTACK2 ) && ( m_flNextRepeatSecondaryAttack > gpGlobals->curtime ) )
|
|
return;
|
|
|
|
// Attack!
|
|
SecondaryAttack();
|
|
return;
|
|
}
|
|
|
|
WeaponIdle();
|
|
}
|
|
|
|
|
|
ConVar sv_weapon_pickup_time_delay("sv_weapon_pickup_time_delay", "0.2f", FCVAR_REPLICATED | FCVAR_CHEAT);
|
|
|
|
bool CBasePortalCombatWeapon::EnoughTimeSinceThrown()
|
|
{
|
|
return gpGlobals->curtime - m_flThrowTime > sv_weapon_pickup_time_delay.GetFloat();
|
|
}
|
|
|
|
float CBasePortalCombatWeapon::GetThrowTime()
|
|
{
|
|
return m_flThrowTime;
|
|
}
|
|
|
|
void CBasePortalCombatWeapon::Drop( const Vector& vecVelocity )
|
|
{
|
|
// Store time when we threw the gun so we dont go and pick up the gun too soon
|
|
m_flThrowTime = gpGlobals->curtime;
|
|
m_pLastOwner = GetOwner();
|
|
|
|
BaseClass::Drop( vecVelocity );
|
|
}
|
|
|
|
CBaseEntity* CBasePortalCombatWeapon::GetLastOwner()
|
|
{
|
|
return m_pLastOwner;
|
|
}
|