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.
346 lines
9.5 KiB
346 lines
9.5 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//============================================================================= |
|
|
|
#include "cbase.h" |
|
#include "tf_weapon_invis.h" |
|
#include "in_buttons.h" |
|
|
|
#if !defined( CLIENT_DLL ) |
|
#include "vguiscreen.h" |
|
#include "tf_player.h" |
|
#else |
|
#include "c_tf_player.h" |
|
#endif |
|
|
|
extern ConVar tf_spy_invis_unstealth_time; |
|
extern ConVar tf_spy_cloak_consume_rate; |
|
extern ConVar tf_spy_cloak_regen_rate; |
|
|
|
//============================================================================= |
|
// |
|
// TFWeaponBase Melee tables. |
|
// |
|
IMPLEMENT_NETWORKCLASS_ALIASED( TFWeaponInvis, DT_TFWeaponInvis ) |
|
|
|
BEGIN_NETWORK_TABLE( CTFWeaponInvis, DT_TFWeaponInvis ) |
|
END_NETWORK_TABLE() |
|
|
|
BEGIN_PREDICTION_DATA( CTFWeaponInvis ) |
|
END_PREDICTION_DATA() |
|
|
|
LINK_ENTITY_TO_CLASS( tf_weapon_invis, CTFWeaponInvis ); |
|
PRECACHE_WEAPON_REGISTER( tf_weapon_invis ); |
|
|
|
// Server specific. |
|
#if !defined( CLIENT_DLL ) |
|
BEGIN_DATADESC( CTFWeaponInvis ) |
|
END_DATADESC() |
|
#endif |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Use the offhand view model |
|
//----------------------------------------------------------------------------- |
|
void CTFWeaponInvis::Spawn( void ) |
|
{ |
|
BaseClass::Spawn(); |
|
|
|
SetViewModelIndex( 1 ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFWeaponInvis::OnActiveStateChanged( int iOldState ) |
|
{ |
|
BaseClass::OnActiveStateChanged( iOldState ); |
|
|
|
// If we are being removed, we need to remove all stealth effects from our owner |
|
if ( m_iState == WEAPON_NOT_CARRIED && iOldState != WEAPON_NOT_CARRIED ) |
|
{ |
|
CleanupInvisibilityWatch(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Clear out the view model when we hide |
|
//----------------------------------------------------------------------------- |
|
void CTFWeaponInvis::HideThink( void ) |
|
{ |
|
SetWeaponVisible( false ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
const char *CTFWeaponInvis::GetViewModel( int viewmodelindex ) const |
|
{ |
|
// Watch uses the player model as its viewmodel, because it's never seen being carried by the player |
|
const CEconItemView *pItem = GetAttributeContainer()->GetItem(); |
|
if ( pItem->IsValid() ) |
|
{ |
|
int iClass = 0; |
|
int iTeam = 0; |
|
CTFPlayer *pTFPlayer = ToTFPlayer( GetOwnerEntity() ); |
|
if ( pTFPlayer ) |
|
{ |
|
iClass = pTFPlayer->GetPlayerClass()->GetClassIndex(); |
|
iTeam = pTFPlayer->GetTeamNumber(); |
|
} |
|
|
|
return pItem->GetPlayerDisplayModel( iClass, iTeam ); |
|
} |
|
|
|
return BaseClass::GetViewModel( viewmodelindex ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Show/hide weapon and corresponding view model if any |
|
// Input : visible - |
|
//----------------------------------------------------------------------------- |
|
void CTFWeaponInvis::SetWeaponVisible( bool visible ) |
|
{ |
|
CBaseViewModel *vm = NULL; |
|
|
|
CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); |
|
if ( pOwner ) |
|
{ |
|
vm = pOwner->GetViewModel( m_nViewModelIndex ); |
|
} |
|
|
|
if ( visible ) |
|
{ |
|
RemoveEffects( EF_NODRAW ); |
|
if ( vm ) |
|
{ |
|
vm->RemoveEffects( EF_NODRAW ); |
|
} |
|
} |
|
else |
|
{ |
|
AddEffects( EF_NODRAW ); |
|
if ( vm ) |
|
{ |
|
vm->AddEffects( EF_NODRAW ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
bool CTFWeaponInvis::Deploy( void ) |
|
{ |
|
bool b = BaseClass::Deploy(); |
|
|
|
SetWeaponIdleTime( gpGlobals->curtime + 1.5 ); |
|
|
|
return b; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
bool CTFWeaponInvis::Holster( CBaseCombatWeapon *pSwitchingTo ) |
|
{ |
|
bool bHolster = BaseClass::Holster( pSwitchingTo ); |
|
|
|
// far in the future |
|
SetWeaponIdleTime( gpGlobals->curtime + 10 ); |
|
|
|
return bHolster; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void CTFWeaponInvis::PrimaryAttack( void ) |
|
{ |
|
// do nothing |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void CTFWeaponInvis::SecondaryAttack( void ) |
|
{ |
|
// do nothing |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
void CTFWeaponInvis::ItemBusyFrame( void ) |
|
{ |
|
// do nothing |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: the player alt-fired or otherwise activated the functionality of |
|
// the invisibility watch |
|
//----------------------------------------------------------------------------- |
|
bool CTFWeaponInvis::ActivateInvisibilityWatch( void ) |
|
{ |
|
CTFPlayer *pOwner = ToTFPlayer( GetOwner() ); |
|
if ( !pOwner ) |
|
return false; |
|
|
|
SetCloakRates(); |
|
|
|
bool bDoSkill = false; |
|
// If we're in TF_COND_STEALTHED - which means we gave it ourselves - always remove it |
|
// If we're in TF_COND_STEALTHED_USER_BUFF and we have Dead Ringer, allow it to be toggled |
|
// since we're allowed to fire from stealth |
|
if ( pOwner->m_Shared.InCond( TF_COND_STEALTHED ) ) |
|
{ |
|
// De-cloak. |
|
float flDecloakRate = 0.0f; |
|
CALL_ATTRIB_HOOK_FLOAT( flDecloakRate, mult_decloak_rate ); |
|
if ( flDecloakRate <= 0.0f ) |
|
flDecloakRate = 1.0f; |
|
|
|
pOwner->m_Shared.FadeInvis( 1.0f ); |
|
} |
|
else |
|
{ |
|
if ( HasFeignDeath() ) |
|
{ |
|
if ( pOwner->m_Shared.IsFeignDeathReady() ) |
|
{ |
|
// Turn it off... |
|
SetFeignDeathState( false ); |
|
} |
|
else if ( pOwner->m_Shared.GetSpyCloakMeter() == 100.f ) |
|
{ |
|
// Turn it on... |
|
SetFeignDeathState( true ); |
|
} |
|
} |
|
else if ( pOwner->CanGoInvisible() && ( pOwner->m_Shared.GetSpyCloakMeter() > 8.0f ) ) // must have over 10% cloak to start |
|
{ |
|
// Do standard cloak. |
|
pOwner->m_Shared.AddCond( TF_COND_STEALTHED, -1.f, pOwner ); |
|
|
|
#ifdef STAGING_ONLY |
|
if ( pOwner->m_Shared.HasPhaseCloakAbility() ) |
|
{ |
|
pOwner->m_Shared.AddCond( TF_COND_STEALTHED_PHASE, -1.f, pOwner ); |
|
} |
|
#endif // STAGING_ONLY |
|
|
|
bDoSkill = true; |
|
} |
|
} |
|
|
|
if ( bDoSkill ) |
|
{ |
|
pOwner->m_Shared.SetNextStealthTime( gpGlobals->curtime + 0.5 ); |
|
} |
|
else |
|
{ |
|
pOwner->m_Shared.SetNextStealthTime( gpGlobals->curtime + 0.1 ); |
|
} |
|
|
|
return bDoSkill; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: the player has changed loadouts or done something else that causes |
|
// us to clean up any side effects of our watch |
|
//----------------------------------------------------------------------------- |
|
void CTFWeaponInvis::CleanupInvisibilityWatch( void ) |
|
{ |
|
CTFPlayer *pOwner = ToTFPlayer( GetOwner() ); |
|
if ( !pOwner ) |
|
return; |
|
|
|
pOwner->m_Shared.SetFeignDeathReady( false ); |
|
|
|
if ( pOwner->m_Shared.IsStealthed() ) |
|
{ |
|
// De-cloak. |
|
pOwner->m_Shared.FadeInvis( 1.0f ); |
|
} |
|
|
|
pOwner->HolsterOffHandWeapon(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFWeaponInvis::SetFeignDeathState( bool bEnabled ) |
|
{ |
|
CTFPlayer *pOwner = ToTFPlayer( GetOwner() ); |
|
if ( !pOwner ) |
|
return; |
|
|
|
if ( pOwner->m_Shared.InCond( TF_COND_GRAPPLINGHOOK ) ) |
|
return; |
|
|
|
if ( bEnabled ) |
|
{ |
|
pOwner->m_Shared.SetFeignDeathReady( true ); |
|
pOwner->SetOffHandWeapon( this ); |
|
pOwner->m_Shared.SetNextStealthTime( gpGlobals->curtime + 0.5 ); |
|
} |
|
else |
|
{ |
|
pOwner->m_Shared.SetFeignDeathReady( false ); |
|
if ( !pOwner->m_Shared.InCond( TF_COND_STEALTHED ) ) |
|
{ |
|
pOwner->HolsterOffHandWeapon(); |
|
if ( pOwner->GetActiveWeapon() ) |
|
{ |
|
pOwner->GetActiveWeapon()->m_flNextPrimaryAttack = gpGlobals->curtime + 0.1f; |
|
} |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Set the correct cloak consume & regen rates for this item. |
|
//----------------------------------------------------------------------------- |
|
void CTFWeaponInvis::SetCloakRates( void ) |
|
{ |
|
CTFPlayer *pOwner = ToTFPlayer( GetOwner() ); |
|
|
|
float fCloakConsumeRate = tf_spy_cloak_consume_rate.GetFloat(); |
|
float fCloakConsumeFactor = 1.0f; |
|
CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( pOwner, fCloakConsumeFactor, mult_cloak_meter_consume_rate ); // Ask the owner since this attr may come from another weapon |
|
|
|
// This value is a inverse scale and does not match expectations on description |
|
// so we subtract and invert to make it align |
|
// ie 25% (0.75% in schema) makes 10seconds go to 13.3 when we want 12.5 |
|
// 2 - 0.75 = 1.25... 1 / 1.25 = 0.8.. Consume rate "8". 10s / 0.8 = 12.5s |
|
if ( fCloakConsumeFactor < 1.0f ) |
|
{ |
|
fCloakConsumeFactor = 1.0f / (2.0f - fCloakConsumeFactor); |
|
} |
|
|
|
pOwner->m_Shared.SetCloakConsumeRate( fCloakConsumeRate * fCloakConsumeFactor ); |
|
|
|
float fCloakRegenRate = tf_spy_cloak_regen_rate.GetFloat(); |
|
float fCloakRegenFactor = 1.0f; |
|
CALL_ATTRIB_HOOK_FLOAT( fCloakRegenFactor, mult_cloak_meter_regen_rate ); |
|
pOwner->m_Shared.SetCloakRegenRate( fCloakRegenRate * fCloakRegenFactor ); |
|
} |
|
|
|
#ifndef CLIENT_DLL |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Return the right pda panel for the watch model we're using |
|
//----------------------------------------------------------------------------- |
|
void CTFWeaponInvis::GetControlPanelInfo( int nPanelIndex, const char *&pPanelName ) |
|
{ |
|
const char *pszViewModel = GetViewModel(0); |
|
if ( Q_stristr( pszViewModel, "pocket" ) ) |
|
{ |
|
pPanelName = "pda_panel_spy_invis_pocket"; |
|
} |
|
else if ( Q_stristr( pszViewModel, "ttg_watch_spy" ) ) |
|
{ |
|
pPanelName = "pda_panel_spy_invis_pocket_ttg"; |
|
} |
|
else if ( Q_stristr( pszViewModel, "hm_watch" ) ) |
|
{ |
|
pPanelName = "pda_panel_spy_invis_pocket_hm"; |
|
} |
|
else |
|
{ |
|
pPanelName = "pda_panel_spy_invis"; |
|
} |
|
} |
|
|
|
#endif
|
|
|