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.
499 lines
13 KiB
499 lines
13 KiB
![]()
4 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
//=============================================================================
|
||
|
|
||
|
#include "cbase.h"
|
||
|
#include "tf_weapon_buff_item.h"
|
||
|
#include "tf_gamerules.h"
|
||
|
|
||
|
// Client specific.
|
||
|
#ifdef CLIENT_DLL
|
||
|
#include "c_tf_player.h"
|
||
|
#include "c_baseentity.h"
|
||
|
// Server specific.
|
||
|
#else
|
||
|
#include "tf_player.h"
|
||
|
#include "tf_gamestats.h"
|
||
|
#endif
|
||
|
|
||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||
|
#include "tier0/memdbgon.h"
|
||
|
|
||
|
//=============================================================================
|
||
|
//
|
||
|
// Weapon Buff Item tables.
|
||
|
//
|
||
|
IMPLEMENT_NETWORKCLASS_ALIASED( TFBuffItem, DT_TFWeaponBuffItem )
|
||
|
|
||
|
BEGIN_NETWORK_TABLE( CTFBuffItem, DT_TFWeaponBuffItem )
|
||
|
END_NETWORK_TABLE()
|
||
|
|
||
|
BEGIN_PREDICTION_DATA( CTFBuffItem )
|
||
|
END_PREDICTION_DATA()
|
||
|
|
||
|
LINK_ENTITY_TO_CLASS( tf_weapon_buff_item, CTFBuffItem );
|
||
|
PRECACHE_WEAPON_REGISTER( tf_weapon_buff_item );
|
||
|
|
||
|
// Models and Buffs need to be aligned
|
||
|
const char* BannerModels[] =
|
||
|
{
|
||
|
"models/weapons/c_models/c_buffbanner/c_buffbanner.mdl",
|
||
|
#ifdef STAGING_ONLY
|
||
|
"models/workshop/weapons/c_models/c_battalion_buffbanner/c_battalion_buffbanner.mdl",
|
||
|
"models/workshop_partner/weapons/c_models/c_shogun_warbanner/c_shogun_warbanner.mdl",
|
||
|
#else
|
||
|
"models/weapons/c_models/c_battalion_buffbanner/c_batt_buffbanner.mdl",
|
||
|
"models/weapons/c_models/c_shogun_warbanner/c_shogun_warbanner.mdl",
|
||
|
#endif
|
||
|
"models/workshop/weapons/c_models/c_paratooper_pack/c_paratrooper_parachute.mdl"
|
||
|
};
|
||
|
|
||
|
#define CLOSED_PARACHUTE_MDL "models/workshop/weapons/c_models/c_paratooper_pack/c_paratrooper_pack.mdl"
|
||
|
#define OPEN_PARACHUTE_MDL "models/workshop/weapons/c_models/c_paratooper_pack/c_paratrooper_pack_open.mdl"
|
||
|
|
||
|
COMPILE_TIME_ASSERT( ARRAYSIZE( BannerModels ) == NUM_BUFF_ITEM_TYPES );
|
||
|
//=============================================================================
|
||
|
//
|
||
|
// Weapon Buff Item functions.
|
||
|
//
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CTFBuffItem::CTFBuffItem()
|
||
|
{
|
||
|
#ifdef CLIENT_DLL
|
||
|
ListenForGameEvent( "deploy_buff_banner" );
|
||
|
m_iBuffType = -1;
|
||
|
m_hBannerEntity = NULL;
|
||
|
#endif
|
||
|
m_bPlayingHorn = false;
|
||
|
|
||
|
UseClientSideAnimation();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CTFBuffItem::~CTFBuffItem()
|
||
|
{
|
||
|
#ifdef CLIENT_DLL
|
||
|
if ( m_hBannerEntity )
|
||
|
{
|
||
|
m_hBannerEntity->Release();
|
||
|
m_hBannerEntity = NULL;
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFBuffItem::Precache()
|
||
|
{
|
||
|
// Need to make this dynamic, but the item data isn't available here?
|
||
|
for ( int i=0; i<ARRAYSIZE(BannerModels); i++ )
|
||
|
{
|
||
|
PrecacheModel( BannerModels[i] );
|
||
|
}
|
||
|
|
||
|
PrecacheModel( "models/weapons/c_models/c_buffpack/c_buffpack.mdl" );
|
||
|
#ifdef STAGING_ONLY
|
||
|
PrecacheModel( "models/workshop/weapons/c_models/c_battalion_buffpack/c_battalion_buffpack.mdl" );
|
||
|
PrecacheModel( "models/workshop_partner/weapons/c_models/c_shogun_warpack/c_shogun_warpack.mdl" );
|
||
|
#else
|
||
|
PrecacheModel( "models/weapons/c_models/c_battalion_buffpack/c_batt_buffpack.mdl" );
|
||
|
PrecacheModel( "models/weapons/c_models/c_shogun_warpack/c_shogun_warpack.mdl" );
|
||
|
#endif
|
||
|
PrecacheModel( OPEN_PARACHUTE_MDL );
|
||
|
PrecacheModel( CLOSED_PARACHUTE_MDL );
|
||
|
|
||
|
PrecacheScriptSound( "Weapon_BuffBanner.HornRed" );
|
||
|
PrecacheScriptSound( "Weapon_BuffBanner.HornBlue" );
|
||
|
PrecacheScriptSound( "Weapon_BattalionsBackup.HornRed" );
|
||
|
PrecacheScriptSound( "Weapon_BattalionsBackup.HornBlue" );
|
||
|
PrecacheScriptSound( "Weapon_BuffBanner.Flag" );
|
||
|
PrecacheScriptSound( "Samurai.Conch" );
|
||
|
|
||
|
BaseClass::Precache();
|
||
|
}
|
||
|
|
||
|
// -----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// -----------------------------------------------------------------------------
|
||
|
void CTFBuffItem::PrimaryAttack()
|
||
|
{
|
||
|
if ( !CanAttack() )
|
||
|
return;
|
||
|
|
||
|
CTFPlayer* pPlayer = ToTFPlayer( GetPlayerOwner() );
|
||
|
if ( !pPlayer )
|
||
|
return;
|
||
|
|
||
|
if ( pPlayer->m_Shared.GetRageMeter() < 100.f )
|
||
|
return;
|
||
|
|
||
|
if ( m_bPlayingHorn )
|
||
|
return;
|
||
|
|
||
|
if ( pPlayer->GetTeamNumber() == TF_TEAM_RED )
|
||
|
{
|
||
|
pPlayer->DoAnimationEvent( PLAYERANIMEVENT_ATTACK_PRIMARY );
|
||
|
SendWeaponAnim( ACT_VM_PRIMARYATTACK );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pPlayer->DoAnimationEvent( PLAYERANIMEVENT_ATTACK_SECONDARY );
|
||
|
SendWeaponAnim( ACT_VM_SECONDARYATTACK );
|
||
|
}
|
||
|
SetContextThink( &CTFBuffItem::BlowHorn, gpGlobals->curtime + 0.22f, "BlowHorn" );
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Attaches the item to the player.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFBuffItem::Equip( CBaseCombatCharacter* pOwner )
|
||
|
{
|
||
|
BaseClass::Equip( pOwner );
|
||
|
|
||
|
CTFPlayer *pTFPlayer = ToTFPlayer( pOwner );
|
||
|
if ( pTFPlayer )
|
||
|
{
|
||
|
pTFPlayer->m_Shared.SetParachuteEquipped( true );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Remove item from the player.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFBuffItem::Detach( void )
|
||
|
{
|
||
|
CTFPlayer *pTFPlayer = GetTFPlayerOwner();
|
||
|
if ( pTFPlayer )
|
||
|
{
|
||
|
pTFPlayer->m_Shared.SetParachuteEquipped( false );
|
||
|
}
|
||
|
|
||
|
BaseClass::Detach();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFBuffItem::BlowHorn( void )
|
||
|
{
|
||
|
CTFPlayer* pPlayer = ToTFPlayer( GetPlayerOwner() );
|
||
|
if ( !pPlayer )
|
||
|
return;
|
||
|
|
||
|
if ( !pPlayer->IsAlive() )
|
||
|
return;
|
||
|
|
||
|
#ifdef GAME_DLL
|
||
|
// Use the buff type to try and figure out what sort of mesh we have and what
|
||
|
// sort of sound to play. This isn't the cleanest thing in the world.
|
||
|
int iBuffType = 0;
|
||
|
CALL_ATTRIB_HOOK_INT( iBuffType, set_buff_type );
|
||
|
|
||
|
// Samurai conch shell.
|
||
|
if ( iBuffType == EConcheror )
|
||
|
{
|
||
|
pPlayer->EmitSound( "Samurai.Conch" );
|
||
|
}
|
||
|
// Bugle.
|
||
|
else if ( iBuffType == EBuffBanner )
|
||
|
{
|
||
|
if ( pPlayer->GetTeamNumber() == TF_TEAM_BLUE )
|
||
|
{
|
||
|
pPlayer->EmitSound( "Weapon_BuffBanner.HornBlue" );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pPlayer->EmitSound( "Weapon_BuffBanner.HornRed" );
|
||
|
}
|
||
|
}
|
||
|
else if ( iBuffType == EBattalion )
|
||
|
{
|
||
|
if ( pPlayer->GetTeamNumber() == TF_TEAM_BLUE )
|
||
|
{
|
||
|
pPlayer->EmitSound( "Weapon_BattalionsBackup.HornBlue" );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pPlayer->EmitSound( "Weapon_BattalionsBackup.HornRed" );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Strange Tracking
|
||
|
if ( !pPlayer->IsBot() )
|
||
|
{
|
||
|
EconEntity_OnOwnerKillEaterEventNoPartner( dynamic_cast<CEconEntity *>( this ), pPlayer, kKillEaterEvent_BannersDeployed );
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
m_bPlayingHorn = true;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFBuffItem::RaiseFlag( void )
|
||
|
{
|
||
|
CTFPlayer* pPlayer = ToTFPlayer( GetPlayerOwner() );
|
||
|
if ( !pPlayer )
|
||
|
return;
|
||
|
|
||
|
if ( !pPlayer->IsAlive() )
|
||
|
return;
|
||
|
|
||
|
m_bPlayingHorn = false;
|
||
|
|
||
|
int iBuffType = 0;
|
||
|
CALL_ATTRIB_HOOK_INT( iBuffType, set_buff_type );
|
||
|
|
||
|
#if GAME_DLL
|
||
|
// this event needs to be sent before we call ActivateSoldierBuff() below
|
||
|
IGameEvent* event = gameeventmanager->CreateEvent( "deploy_buff_banner" );
|
||
|
if ( event )
|
||
|
{
|
||
|
event->SetInt( "buff_type", iBuffType );
|
||
|
event->SetInt( "buff_owner", pPlayer->GetUserID() );
|
||
|
gameeventmanager->FireEvent( event );
|
||
|
}
|
||
|
|
||
|
pPlayer->EmitSound( "Weapon_BuffBanner.Flag" );
|
||
|
pPlayer->SpeakConceptIfAllowed( MP_CONCEPT_PLAYER_BATTLECRY );
|
||
|
#endif
|
||
|
|
||
|
pPlayer->m_Shared.ActivateRageBuff( this, iBuffType );
|
||
|
pPlayer->SelectLastItem();
|
||
|
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Don't let them holster while they are blowing the horn.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CTFBuffItem::Holster( CBaseCombatWeapon *pSwitchingTo )
|
||
|
{
|
||
|
if ( m_bPlayingHorn )
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return BaseClass::Holster( pSwitchingTo );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFBuffItem::FireGameEvent( IGameEvent* event )
|
||
|
{
|
||
|
#ifdef CLIENT_DLL
|
||
|
const char *name = event->GetName();
|
||
|
|
||
|
if ( 0 == Q_strcmp( name, "deploy_buff_banner" ) )
|
||
|
{
|
||
|
CTFPlayer* pPlayer = ToTFPlayer( ClientEntityList().GetEnt( engine->GetPlayerForUserID( event->GetInt( "buff_owner" ) ) ) );
|
||
|
if ( pPlayer == GetOwner() )
|
||
|
{
|
||
|
CreateBanner();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BaseClass::FireGameEvent( event );
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
// -----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
// -----------------------------------------------------------------------------
|
||
|
void CTFBuffItem::CreateBanner()
|
||
|
{
|
||
|
#ifdef CLIENT_DLL
|
||
|
|
||
|
if ( m_hBannerEntity == NULL )
|
||
|
{
|
||
|
CTFPlayer* pPlayer = ToTFPlayer( GetPlayerOwner() );
|
||
|
if ( !pPlayer || !pPlayer->IsAlive() )
|
||
|
return;
|
||
|
|
||
|
C_TFBuffBanner* pBanner = new C_TFBuffBanner;
|
||
|
if ( !pBanner )
|
||
|
return;
|
||
|
|
||
|
//Assert( iBuffType > 0 );
|
||
|
//Assert( iBuffType <= ARRAYSIZE(BannerModels) );
|
||
|
pBanner->m_nSkin = 0;
|
||
|
pBanner->InitializeAsClientEntity( BannerModels[GetBuffType()-1], RENDER_GROUP_OPAQUE_ENTITY );
|
||
|
pBanner->SetBuffItem( this );
|
||
|
pBanner->SetBuffType( GetBuffType() );
|
||
|
pBanner->ForceClientSideAnimationOn();
|
||
|
SetBanner( pBanner );
|
||
|
int iSpine = pPlayer->LookupBone( "bip_spine_3" );
|
||
|
Assert( iSpine != -1 );
|
||
|
if ( iSpine != -1 )
|
||
|
{
|
||
|
pBanner->AttachEntityToBone( pPlayer, iSpine );
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
#ifdef CLIENT_DLL
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFBuffItem::NotifyShouldTransmit( ShouldTransmitState_t state )
|
||
|
{
|
||
|
if ( state == SHOULDTRANSMIT_END )
|
||
|
{
|
||
|
// Kill the item - It will be recreated later
|
||
|
if ( m_hBannerEntity )
|
||
|
{
|
||
|
m_hBannerEntity->Release();
|
||
|
m_hBannerEntity = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BaseClass::NotifyShouldTransmit( state );
|
||
|
}
|
||
|
|
||
|
void CTFBuffItem::OnDataChanged( DataUpdateType_t updateType )
|
||
|
{
|
||
|
if ( updateType == DATA_UPDATE_CREATED )
|
||
|
{
|
||
|
SetNextClientThink( CLIENT_THINK_ALWAYS );
|
||
|
}
|
||
|
|
||
|
BaseClass::OnDataChanged( updateType );
|
||
|
}
|
||
|
|
||
|
void CTFBuffItem::ClientThink( void )
|
||
|
{
|
||
|
if ( m_iBuffType == -1 || m_iBuffType == 0 )
|
||
|
{
|
||
|
m_iBuffType = GetBuffType();
|
||
|
|
||
|
if ( m_iBuffType != EParachute )
|
||
|
{
|
||
|
SetNextClientThink( CLIENT_THINK_NEVER );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif // CLIENT_DLL
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFBuffItem::WeaponReset( void )
|
||
|
{
|
||
|
BaseClass::WeaponReset();
|
||
|
|
||
|
m_bPlayingHorn = false;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CTFBuffItem::SendWeaponAnim( int iActivity )
|
||
|
{
|
||
|
CTFPlayer *pPlayer = GetTFPlayerOwner();
|
||
|
if ( !pPlayer )
|
||
|
return BaseClass::SendWeaponAnim( iActivity );
|
||
|
|
||
|
switch ( iActivity )
|
||
|
{
|
||
|
case ACT_VM_DRAW:
|
||
|
iActivity = ACT_ITEM1_VM_DRAW;
|
||
|
break;
|
||
|
case ACT_VM_HOLSTER:
|
||
|
iActivity = ACT_ITEM1_VM_HOLSTER;
|
||
|
break;
|
||
|
case ACT_VM_IDLE:
|
||
|
if ( m_bPlayingHorn )
|
||
|
{
|
||
|
RaiseFlag();
|
||
|
iActivity = ACT_RESET;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
iActivity = ACT_ITEM1_VM_IDLE;
|
||
|
}
|
||
|
break;
|
||
|
case ACT_VM_PULLBACK:
|
||
|
iActivity = ACT_ITEM1_VM_PULLBACK;
|
||
|
break;
|
||
|
case ACT_VM_PRIMARYATTACK:
|
||
|
m_bPlayingHorn = true;
|
||
|
iActivity = ACT_ITEM1_VM_PRIMARYATTACK;
|
||
|
break;
|
||
|
case ACT_VM_SECONDARYATTACK:
|
||
|
m_bPlayingHorn = true;
|
||
|
iActivity = ACT_ITEM1_VM_SECONDARYATTACK;
|
||
|
break;
|
||
|
case ACT_VM_IDLE_TO_LOWERED:
|
||
|
iActivity = ACT_ITEM1_VM_IDLE_TO_LOWERED;
|
||
|
break;
|
||
|
case ACT_VM_IDLE_LOWERED:
|
||
|
iActivity = ACT_ITEM1_VM_IDLE_LOWERED;
|
||
|
break;
|
||
|
case ACT_VM_LOWERED_TO_IDLE:
|
||
|
iActivity = ACT_ITEM1_VM_LOWERED_TO_IDLE;
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return BaseClass::SendWeaponAnim( iActivity );
|
||
|
}
|
||
|
|
||
|
bool CTFBuffItem::CanReload( void )
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: UI Progress
|
||
|
//-----------------------------------------------------------------------------
|
||
|
float CTFBuffItem::GetProgress( void )
|
||
|
{
|
||
|
CTFPlayer *pPlayer = GetTFPlayerOwner();
|
||
|
if ( !pPlayer )
|
||
|
return 0.f;
|
||
|
|
||
|
return pPlayer->m_Shared.GetRageMeter() / 100.0f;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: UI Progress (same as GetProgress() without the division by 100.0f)
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CTFBuffItem::IsFull( void )
|
||
|
{
|
||
|
CTFPlayer *pPlayer = GetTFPlayerOwner();
|
||
|
if ( !pPlayer )
|
||
|
return false;
|
||
|
|
||
|
return ( pPlayer->m_Shared.GetRageMeter() >= 100.0f );
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CTFBuffItem::EffectMeterShouldFlash( void )
|
||
|
{
|
||
|
CTFPlayer *pPlayer = GetTFPlayerOwner();
|
||
|
if ( !pPlayer )
|
||
|
return false;
|
||
|
|
||
|
if ( pPlayer && (IsFull() || pPlayer->m_Shared.IsRageDraining()) )
|
||
|
return true;
|
||
|
else
|
||
|
return false;
|
||
|
}
|