mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-10 18:59:36 +00:00
1
This commit is contained in:
@@ -0,0 +1,579 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include "cbase.h"
|
||||
#include "tf_weapon_wrench.h"
|
||||
#include "decals.h"
|
||||
#include "baseobject_shared.h"
|
||||
#include "tf_viewmodel.h"
|
||||
|
||||
// Client specific.
|
||||
#ifdef CLIENT_DLL
|
||||
#include "c_tf_player.h"
|
||||
#include "in_buttons.h"
|
||||
#include "tf_hud_menu_eureka_teleport.h"
|
||||
// NVNT haptics system interface
|
||||
#include "haptics/ihaptics.h"
|
||||
// Server specific.
|
||||
#else
|
||||
#include "tf_player.h"
|
||||
#include "variant_t.h"
|
||||
#include "tf_gamerules.h"
|
||||
#include "particle_parse.h"
|
||||
#include "tf_fx.h"
|
||||
#include "tf_obj_sentrygun.h"
|
||||
#endif
|
||||
|
||||
// Maximum time between robo arm hits to maintain the three-hit-combo
|
||||
#define ROBOARM_COMBO_TIMEOUT 1.0f
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Weapon Wrench tables.
|
||||
//
|
||||
IMPLEMENT_NETWORKCLASS_ALIASED( TFWrench, DT_TFWeaponWrench )
|
||||
|
||||
BEGIN_NETWORK_TABLE( CTFWrench, DT_TFWeaponWrench )
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
BEGIN_PREDICTION_DATA( CTFWrench )
|
||||
END_PREDICTION_DATA()
|
||||
|
||||
LINK_ENTITY_TO_CLASS( tf_weapon_wrench, CTFWrench );
|
||||
PRECACHE_WEAPON_REGISTER( tf_weapon_wrench );
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Robot Arm tables.
|
||||
//
|
||||
IMPLEMENT_NETWORKCLASS_ALIASED( TFRobotArm, DT_TFWeaponRobotArm )
|
||||
|
||||
BEGIN_NETWORK_TABLE( CTFRobotArm, DT_TFWeaponRobotArm )
|
||||
#ifdef GAME_DLL
|
||||
SendPropEHandle(SENDINFO(m_hRobotArm)),
|
||||
#else
|
||||
RecvPropEHandle(RECVINFO(m_hRobotArm)),
|
||||
#endif
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
BEGIN_PREDICTION_DATA( CTFRobotArm )
|
||||
// DEFINE_PRED_FIELD( name, fieldtype, flags )
|
||||
DEFINE_PRED_FIELD( m_iComboCount, FIELD_INTEGER, 0 ),
|
||||
DEFINE_PRED_FIELD( m_flLastComboHit, FIELD_FLOAT, 0 ),
|
||||
END_PREDICTION_DATA()
|
||||
#endif
|
||||
|
||||
LINK_ENTITY_TO_CLASS( tf_weapon_robot_arm, CTFRobotArm );
|
||||
PRECACHE_WEAPON_REGISTER( tf_weapon_robot_arm );
|
||||
|
||||
IMPLEMENT_NETWORKCLASS_ALIASED( TFWearableRobotArm, DT_TFWearableRobotArm )
|
||||
|
||||
BEGIN_NETWORK_TABLE( CTFWearableRobotArm, DT_TFWearableRobotArm )
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
LINK_ENTITY_TO_CLASS( tf_wearable_robot_arm, CTFWearableRobotArm );
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Weapon Wrench functions.
|
||||
//
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CTFWrench::CTFWrench()
|
||||
: m_bReloadDown( false )
|
||||
{}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFWrench::Spawn()
|
||||
{
|
||||
BaseClass::Spawn();
|
||||
}
|
||||
|
||||
|
||||
#ifdef GAME_DLL
|
||||
void CTFWrench::OnFriendlyBuildingHit( CBaseObject *pObject, CTFPlayer *pPlayer, Vector hitLoc )
|
||||
{
|
||||
bool bHelpTeammateBuildStructure = pObject->IsBuilding() && pObject->GetOwner() != GetOwner();
|
||||
|
||||
// Did this object hit do any work? repair or upgrade?
|
||||
bool bUsefulHit = pObject->InputWrenchHit( pPlayer, this, hitLoc );
|
||||
|
||||
// award achievement if we helped a teammate build a structure
|
||||
if ( bUsefulHit && bHelpTeammateBuildStructure )
|
||||
{
|
||||
CTFPlayer *pOwner = ToTFPlayer( GetOwner() );
|
||||
if ( pOwner && pOwner->IsPlayerClass( TF_CLASS_ENGINEER ) )
|
||||
{
|
||||
pOwner->AwardAchievement( ACHIEVEMENT_TF_ENGINEER_HELP_BUILD_STRUCTURE );
|
||||
}
|
||||
}
|
||||
|
||||
CDisablePredictionFiltering disabler;
|
||||
|
||||
if ( pObject->IsDisposableBuilding() )
|
||||
{
|
||||
CSingleUserRecipientFilter singleFilter( pPlayer );
|
||||
EmitSound( singleFilter, pObject->entindex(), "Player.UseDeny" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( bUsefulHit )
|
||||
{
|
||||
// play success sound
|
||||
WeaponSound( SPECIAL1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// play failure sound
|
||||
WeaponSound( SPECIAL2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void CTFWrench::Smack( void )
|
||||
{
|
||||
// see if we can hit an object with a higher range
|
||||
|
||||
// Get the current player.
|
||||
CTFPlayer *pPlayer = GetTFPlayerOwner();
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
if ( !CanAttack() )
|
||||
return;
|
||||
|
||||
// Setup a volume for the melee weapon to be swung - approx size, so all melee behave the same.
|
||||
static Vector vecSwingMins( -18, -18, -18 );
|
||||
static Vector vecSwingMaxs( 18, 18, 18 );
|
||||
|
||||
// Setup the swing range.
|
||||
Vector vecForward;
|
||||
AngleVectors( pPlayer->EyeAngles(), &vecForward );
|
||||
Vector vecSwingStart = pPlayer->Weapon_ShootPosition();
|
||||
Vector vecSwingEnd = vecSwingStart + vecForward * 70;
|
||||
|
||||
// only trace against objects
|
||||
|
||||
// See if we hit anything.
|
||||
trace_t trace;
|
||||
|
||||
CTraceFilterIgnorePlayers traceFilter( NULL, COLLISION_GROUP_NONE );
|
||||
UTIL_TraceLine( vecSwingStart, vecSwingEnd, MASK_SOLID, &traceFilter, &trace );
|
||||
if ( trace.fraction >= 1.0 )
|
||||
{
|
||||
UTIL_TraceHull( vecSwingStart, vecSwingEnd, vecSwingMins, vecSwingMaxs, MASK_SOLID, &traceFilter, &trace );
|
||||
}
|
||||
|
||||
// We hit, setup the smack.
|
||||
if ( trace.fraction < 1.0f &&
|
||||
trace.m_pEnt &&
|
||||
trace.m_pEnt->IsBaseObject() &&
|
||||
trace.m_pEnt->GetTeamNumber() == pPlayer->GetTeamNumber() )
|
||||
{
|
||||
#ifdef GAME_DLL
|
||||
OnFriendlyBuildingHit( dynamic_cast< CBaseObject * >( trace.m_pEnt ), pPlayer, trace.endpos );
|
||||
#else
|
||||
// NVNT if the local player is the owner of this wrench
|
||||
// Notify the haptics system we just repaired something.
|
||||
if(pPlayer==C_TFPlayer::GetLocalTFPlayer() && haptics)
|
||||
haptics->ProcessHapticEvent(2,"Weapons","tf_weapon_wrench_fix");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we cannot, Smack as usual for player hits
|
||||
BaseClass::Smack();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFWrench::ItemPostFrame()
|
||||
{
|
||||
BaseClass::ItemPostFrame();
|
||||
|
||||
if ( !CanAttack() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CTFPlayer *pOwner = ToTFPlayer( GetOwnerEntity() );
|
||||
if ( !pOwner )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Just pressed reload?
|
||||
if ( pOwner->m_nButtons & IN_RELOAD && !m_bReloadDown )
|
||||
{
|
||||
m_bReloadDown = true;
|
||||
int iAltFireTeleportToSpawn = 0;
|
||||
CALL_ATTRIB_HOOK_INT( iAltFireTeleportToSpawn, alt_fire_teleport_to_spawn );
|
||||
if ( iAltFireTeleportToSpawn )
|
||||
{
|
||||
// Tell the teleport menu to show
|
||||
CHudEurekaEffectTeleportMenu *pTeleportMenu = ( CHudEurekaEffectTeleportMenu * )GET_HUDELEMENT( CHudEurekaEffectTeleportMenu );
|
||||
if ( pTeleportMenu )
|
||||
{
|
||||
pTeleportMenu->WantsToTeleport();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( !(pOwner->m_nButtons & IN_RELOAD) && m_bReloadDown )
|
||||
{
|
||||
m_bReloadDown = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Kill all buildings when wrench is changed.
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifdef GAME_DLL
|
||||
void CTFWrench::Equip( CBaseCombatCharacter *pOwner )
|
||||
{
|
||||
// STAGING_ENGY
|
||||
CTFPlayer *pPlayer = ToTFPlayer( pOwner );
|
||||
if ( pPlayer )
|
||||
{
|
||||
// if switching too gunslinger, blow up other sentry
|
||||
int iMiniSentry = 0;
|
||||
CALL_ATTRIB_HOOK_INT( iMiniSentry, wrench_builds_minisentry );
|
||||
if ( iMiniSentry )
|
||||
{
|
||||
// Just detonate Sentries
|
||||
CObjectSentrygun *pSentry = dynamic_cast<CObjectSentrygun*>( pPlayer->GetObjectOfType( OBJ_SENTRYGUN ) );
|
||||
if ( pSentry )
|
||||
{
|
||||
pSentry->DetonateObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BaseClass::Equip( pOwner );
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Kill all buildings when wrench is changed.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFWrench::Detach( void )
|
||||
{
|
||||
// STAGING_ENGY
|
||||
CTFPlayer *pPlayer = GetTFPlayerOwner();
|
||||
if ( pPlayer )
|
||||
{
|
||||
bool bDetonateObjects = true;
|
||||
|
||||
// In MvM mode, leave engineer's buildings after he dies
|
||||
if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() )
|
||||
{
|
||||
if ( pPlayer->GetTeamNumber() != TF_TEAM_PVE_DEFENDERS )
|
||||
{
|
||||
bDetonateObjects = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Only detonate if we are unequipping gunslinger
|
||||
if ( bDetonateObjects )
|
||||
{
|
||||
// if switching off of gunslinger detonate
|
||||
int iMiniSentry = 0;
|
||||
CALL_ATTRIB_HOOK_INT( iMiniSentry, wrench_builds_minisentry );
|
||||
if ( iMiniSentry )
|
||||
{
|
||||
// Just detonate Sentries
|
||||
CObjectSentrygun *pSentry = dynamic_cast<CObjectSentrygun*>( pPlayer->GetObjectOfType( OBJ_SENTRYGUN ) );
|
||||
if ( pSentry )
|
||||
{
|
||||
pSentry->DetonateObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BaseClass::Detach();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Apply health upgrade to our existing buildings
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFWrench::ApplyBuildingHealthUpgrade( void )
|
||||
{
|
||||
CTFPlayer *pPlayer = GetTFPlayerOwner();
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
for ( int i = pPlayer->GetObjectCount()-1; i >= 0; i-- )
|
||||
{
|
||||
CBaseObject *pObj = pPlayer->GetObject(i);
|
||||
if ( pObj )
|
||||
{
|
||||
pObj->ApplyHealthUpgrade();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// STAGING_ENGY
|
||||
ConVar tf_construction_build_rate_multiplier( "tf_construction_build_rate_multiplier", "1.5f", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY );
|
||||
float CTFWrench::GetConstructionValue( void )
|
||||
{
|
||||
float flValue = tf_construction_build_rate_multiplier.GetFloat();
|
||||
CALL_ATTRIB_HOOK_FLOAT( flValue, mult_construction_value );
|
||||
return flValue;
|
||||
}
|
||||
|
||||
float CTFWrench::GetRepairValue( void )
|
||||
{
|
||||
float flValue = 1.0;
|
||||
CALL_ATTRIB_HOOK_FLOAT( flValue, mult_repair_value );
|
||||
|
||||
#ifdef GAME_DLL
|
||||
if ( GetOwner() )
|
||||
{
|
||||
CBaseCombatWeapon* pWpn = GetOwner()->Weapon_GetSlot( TF_WPN_TYPE_PRIMARY );
|
||||
if ( pWpn )
|
||||
{
|
||||
CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( pWpn, flValue, mult_repair_value );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return flValue;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CTFWrench::Holster( CBaseCombatWeapon *pSwitchingTo )
|
||||
{
|
||||
return BaseClass::Holster( pSwitchingTo );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CTFRobotArm::CTFRobotArm()
|
||||
{
|
||||
m_iComboCount = 0;
|
||||
m_flLastComboHit = 0.f;
|
||||
m_bBigIdle = false;
|
||||
m_bBigHit = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFRobotArm::Precache()
|
||||
{
|
||||
BaseClass::Precache();
|
||||
|
||||
extern const char *g_HACK_GunslingerEngineerArmsOverride;
|
||||
PrecacheModel( g_HACK_GunslingerEngineerArmsOverride );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifdef GAME_DLL
|
||||
void CTFRobotArm::Equip( CBaseCombatCharacter* pOwner )
|
||||
{
|
||||
BaseClass::Equip( pOwner );
|
||||
|
||||
if ( !IsPDQ() )
|
||||
return;
|
||||
|
||||
CTFWearable* pArmItem = dynamic_cast<CTFWearable*>( CreateEntityByName( "tf_wearable_robot_arm" ) );
|
||||
if ( pArmItem )
|
||||
{
|
||||
pArmItem->AddSpawnFlags( SF_NORESPAWN );
|
||||
pArmItem->SetAlwaysAllow( true );
|
||||
DispatchSpawn( pArmItem );
|
||||
pArmItem->GiveTo( pOwner );
|
||||
pArmItem->AddHiddenBodyGroup( "rightarm" );
|
||||
pArmItem->SetOwnerEntity( pOwner );
|
||||
m_hRobotArm.Set( pArmItem );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFRobotArm::Drop( const Vector &vecVelocity )
|
||||
{
|
||||
RemoveRobotArm();
|
||||
|
||||
BaseClass::Drop( vecVelocity );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFRobotArm::UpdateOnRemove( void )
|
||||
{
|
||||
RemoveRobotArm();
|
||||
|
||||
BaseClass::UpdateOnRemove();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFRobotArm::RemoveRobotArm( void )
|
||||
{
|
||||
if ( m_hRobotArm )
|
||||
{
|
||||
m_hRobotArm->RemoveFrom( GetOwnerEntity() );
|
||||
m_hRobotArm = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFRobotArm::OnActiveStateChanged( int iOldState )
|
||||
{
|
||||
if ( m_iState == WEAPON_NOT_CARRIED )
|
||||
{
|
||||
RemoveRobotArm();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// -----------------------------------------------------------------------------
|
||||
void CTFRobotArm::PrimaryAttack()
|
||||
{
|
||||
CTFPlayer *pPlayer = GetTFPlayerOwner();
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
if ( gpGlobals->curtime - m_flLastComboHit > ROBOARM_COMBO_TIMEOUT )
|
||||
{
|
||||
m_iComboCount = 0;
|
||||
}
|
||||
|
||||
if ( m_iComboCount == 2 && CanAttack() )
|
||||
{
|
||||
pPlayer->m_Shared.SetNextMeleeCrit( MELEE_CRIT );
|
||||
}
|
||||
|
||||
BaseClass::PrimaryAttack();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFRobotArm::Smack( void )
|
||||
{
|
||||
CTFPlayer *pPlayer = GetTFPlayerOwner();
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
trace_t trace;
|
||||
bool btrace = DoSwingTrace( trace );
|
||||
if ( btrace && trace.DidHitNonWorldEntity() && trace.m_pEnt && trace.m_pEnt->IsPlayer() &&
|
||||
trace.m_pEnt->GetTeamNumber() != pPlayer->GetTeamNumber() )
|
||||
{
|
||||
m_iComboCount++;
|
||||
m_flLastComboHit = gpGlobals->curtime;
|
||||
|
||||
if ( m_iComboCount == 3 )
|
||||
{
|
||||
m_iComboCount = 0;
|
||||
m_bBigIdle = true;
|
||||
m_bBigHit = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_iComboCount = 0;
|
||||
}
|
||||
|
||||
BaseClass::Smack();
|
||||
|
||||
m_bBigHit = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFRobotArm::DoViewModelAnimation( void )
|
||||
{
|
||||
if ( m_iComboCount == 2 )
|
||||
{
|
||||
SendWeaponAnim( ACT_ITEM2_VM_SWINGHARD );
|
||||
}
|
||||
else
|
||||
{
|
||||
SendWeaponAnim( ACT_ITEM2_VM_HITCENTER );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifdef GAME_DLL
|
||||
int CTFRobotArm::GetDamageCustom()
|
||||
{
|
||||
if ( m_bBigHit )
|
||||
{
|
||||
return TF_DMG_CUSTOM_COMBO_PUNCH;
|
||||
}
|
||||
else
|
||||
{
|
||||
return BaseClass::GetDamageCustom();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
float CTFRobotArm::GetForceScale( void )
|
||||
{
|
||||
if ( m_bBigHit )
|
||||
{
|
||||
return 500.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
return BaseClass::GetForceScale();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFRobotArm::WeaponIdle( void )
|
||||
{
|
||||
#ifdef GAME_DLL
|
||||
if ( m_bBigIdle )
|
||||
{
|
||||
m_bBigIdle = false;
|
||||
SendWeaponAnim( ACT_ITEM2_VM_IDLE_2 );
|
||||
m_flTimeWeaponIdle = gpGlobals->curtime + SequenceDuration();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
BaseClass::WeaponIdle();
|
||||
}
|
||||
Reference in New Issue
Block a user