summaryrefslogtreecommitdiff
path: root/game/shared/tf/tf_weapon_buff_item.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/shared/tf/tf_weapon_buff_item.cpp')
-rw-r--r--game/shared/tf/tf_weapon_buff_item.cpp498
1 files changed, 498 insertions, 0 deletions
diff --git a/game/shared/tf/tf_weapon_buff_item.cpp b/game/shared/tf/tf_weapon_buff_item.cpp
new file mode 100644
index 0000000..3055bf5
--- /dev/null
+++ b/game/shared/tf/tf_weapon_buff_item.cpp
@@ -0,0 +1,498 @@
+//========= 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;
+}