summaryrefslogtreecommitdiff
path: root/game/client/tf/c_tf_weapon_builder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/client/tf/c_tf_weapon_builder.cpp')
-rw-r--r--game/client/tf/c_tf_weapon_builder.cpp460
1 files changed, 460 insertions, 0 deletions
diff --git a/game/client/tf/c_tf_weapon_builder.cpp b/game/client/tf/c_tf_weapon_builder.cpp
new file mode 100644
index 0000000..cc83513
--- /dev/null
+++ b/game/client/tf/c_tf_weapon_builder.cpp
@@ -0,0 +1,460 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Client's CWeaponBuilder class
+//
+// $Workfile: $
+// $Date: $
+// $NoKeywords: $
+//=============================================================================//
+#include "cbase.h"
+#include "hud.h"
+#include "in_buttons.h"
+#include "clientmode_tf.h"
+#include "engine/IEngineSound.h"
+#include "c_tf_weapon_builder.h"
+#include "c_weapon__stubs.h"
+#include "iinput.h"
+#include <vgui/IVGui.h>
+#include "c_tf_player.h"
+#include "c_vguiscreen.h"
+#include "ienginevgui.h"
+
+STUB_WEAPON_CLASS_IMPLEMENT( tf_weapon_builder, C_TFWeaponBuilder );
+PRECACHE_WEAPON_REGISTER( tf_weapon_builder );
+
+// SUPER HACK TO FIX DEMOS. For a couple days, we accidently renamed
+// CTFWeaponBuilder to C_TFWeaponBuilder on the server. This was fine for
+// playing the game but broke all previously recorded demos. Fixing this and
+// re-renaming the class back to the original name fixed all demos recorded
+// with the brokenly-renamed class. To handle these demos that think the class
+// is called C_TFWeaponBuilder on the server, we're creating a new class that derives from
+// the real C_TFWeaponBuilder and does nothing special except that it calls
+// IMPLEMENT_CLIENTCLASS and maps itself to serverclass "C_TFWeaponBuilder"
+// (which, if you've followed along, doesn't exist anymore).
+//
+// As a history lesson, this broke from the change in tf_player_shared.h in cl 1722245
+class C_TFWeaponBuilderReplayHack : public C_TFWeaponBuilder
+{
+ DECLARE_CLASS( C_TFWeaponBuilderReplayHack, C_TFWeaponBuilder );
+public:
+ DECLARE_CLIENTCLASS();
+ DECLARE_PREDICTABLE();
+};
+IMPLEMENT_CLIENTCLASS( C_TFWeaponBuilderReplayHack, DT_TFWeaponBuilder, C_TFWeaponBuilder )
+BEGIN_PREDICTION_DATA( C_TFWeaponBuilderReplayHack )
+END_PREDICTION_DATA()
+
+
+IMPLEMENT_NETWORKCLASS_ALIASED( TFWeaponBuilder, DT_TFWeaponBuilder )
+
+// Recalc object sprite when we receive a new object type to build
+void RecvProxy_ObjectType( const CRecvProxyData *pData, void *pStruct, void *pOut )
+{
+ // Pass to normal Int recvproxy
+ RecvProxy_Int32ToInt32( pData, pStruct, pOut );
+
+ // Reset the object sprite
+ C_TFWeaponBuilder *pBuilder = ( C_TFWeaponBuilder * )pStruct;
+ pBuilder->SetupObjectSelectionSprite();
+}
+
+BEGIN_NETWORK_TABLE_NOBASE( C_TFWeaponBuilder, DT_BuilderLocalData )
+ RecvPropInt( RECVINFO(m_iObjectType), 0, RecvProxy_ObjectType ),
+ RecvPropEHandle( RECVINFO(m_hObjectBeingBuilt) ),
+ RecvPropArray3( RECVINFO_ARRAY( m_aBuildableObjectTypes ), RecvPropBool( RECVINFO( m_aBuildableObjectTypes[0] ) ) ),
+END_NETWORK_TABLE()
+
+BEGIN_NETWORK_TABLE( C_TFWeaponBuilder, DT_TFWeaponBuilder )
+ RecvPropInt( RECVINFO(m_iBuildState) ),
+ RecvPropDataTable( "BuilderLocalData", 0, 0, &REFERENCE_RECV_TABLE( DT_BuilderLocalData ) ),
+ RecvPropInt( RECVINFO(m_iObjectMode) ),
+ RecvPropFloat( RECVINFO( m_flWheatleyTalkingUntil) ),
+END_RECV_TABLE()
+
+
+
+
+//-----------------------------------------------------------------------------
+IMPLEMENT_NETWORKCLASS_ALIASED( TFWeaponSapper, DT_TFWeaponSapper )
+BEGIN_NETWORK_TABLE( C_TFWeaponSapper, DT_TFWeaponSapper )
+ RecvPropFloat( RECVINFO( m_flChargeBeginTime ) ),
+END_NETWORK_TABLE()
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+C_TFWeaponBuilder::C_TFWeaponBuilder()
+{
+ m_iBuildState = 0;
+ m_iObjectType = BUILDER_INVALID_OBJECT;
+ m_pSelectionTextureActive = NULL;
+ m_pSelectionTextureInactive = NULL;
+ m_iValidBuildPoseParam = -1;
+ m_flWheatleyTalkingUntil = 0;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+C_TFWeaponBuilder::~C_TFWeaponBuilder()
+{
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Output : char const
+//-----------------------------------------------------------------------------
+const char *C_TFWeaponBuilder::GetCurrentSelectionObjectName( void )
+{
+ if ( m_iObjectType == -1 || (m_iBuildState == BS_SELECTING) )
+ return "";
+
+ return GetObjectInfo( m_iObjectType )->m_pBuilderWeaponName;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool C_TFWeaponBuilder::Deploy( void )
+{
+ bool bDeploy = BaseClass::Deploy();
+
+ if ( bDeploy )
+ {
+ m_flNextPrimaryAttack = gpGlobals->curtime + 0.35f;
+ m_flNextSecondaryAttack = gpGlobals->curtime; // asap
+
+ CTFPlayer *pPlayer = ToTFPlayer( GetOwner() );
+ if (!pPlayer)
+ return false;
+
+ pPlayer->SetNextAttack( gpGlobals->curtime );
+
+ m_iWorldModelIndex = modelinfo->GetModelIndex( GetWorldModel() );
+ }
+
+ return bDeploy;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void C_TFWeaponBuilder::SecondaryAttack( void )
+{
+ if ( m_bInAttack2 )
+ return;
+
+ // require a re-press
+ m_bInAttack2 = true;
+
+ CTFPlayer *pOwner = ToTFPlayer( GetOwner() );
+ if ( !pOwner )
+ return;
+
+ pOwner->DoClassSpecialSkill();
+
+ m_flNextSecondaryAttack = gpGlobals->curtime + 0.2f;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: cache the build pos pose param
+//-----------------------------------------------------------------------------
+CStudioHdr *C_TFWeaponBuilder::OnNewModel( void )
+{
+ CStudioHdr *hdr = BaseClass::OnNewModel();
+
+ m_iValidBuildPoseParam = LookupPoseParameter( "valid_build_pos" );
+
+ return hdr;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// ----------------------------------------------------------------------------
+void C_TFWeaponBuilder::PostDataUpdate( DataUpdateType_t type )
+{
+ if ( type == DATA_UPDATE_CREATED )
+ {
+ // m_iViewModelIndex is set by the base Precache(), which didn't know what
+ // type of object we built, so it didn't get the right viewmodel index.
+ // Now that our data is filled in, go and get the right index.
+ const char *pszViewModel = GetViewModel(0);
+ if ( pszViewModel && pszViewModel[0] )
+ {
+ m_iViewModelIndex = CBaseEntity::PrecacheModel( pszViewModel );
+ }
+ }
+
+ BaseClass::PostDataUpdate( type );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: only called for local player
+//-----------------------------------------------------------------------------
+void C_TFWeaponBuilder::Redraw()
+{
+ if ( m_iValidBuildPoseParam >= 0 )
+ {
+ CTFPlayer *pOwner = ToTFPlayer( GetOwner() );
+ if ( !pOwner )
+ return;
+
+ // Assuming here that our model is the same as our viewmodel's model!
+ CBaseViewModel *pViewModel = pOwner->GetViewModel(0);
+
+ if ( pViewModel )
+ {
+ float flPoseParamValue = pViewModel->GetPoseParameter( m_iValidBuildPoseParam );
+
+ C_BaseObject *pObj = m_hObjectBeingBuilt.Get();
+
+ if ( pObj && pObj->WasLastPlacementPosValid() )
+ {
+ // pose param approach 1.0
+ flPoseParamValue = Approach( 1.0, flPoseParamValue, 3.0 * gpGlobals->frametime );
+ }
+ else
+ {
+ // pose param approach 0.0
+ flPoseParamValue = Approach( 0.0, flPoseParamValue, 1.5 * gpGlobals->frametime );
+ }
+
+ pViewModel->SetPoseParameter( m_iValidBuildPoseParam, flPoseParamValue );
+ }
+ }
+
+ BaseClass::Redraw();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Output : Returns true on success, false on failure.
+//-----------------------------------------------------------------------------
+bool C_TFWeaponBuilder::IsPlacingObject( void )
+{
+ if ( m_iBuildState == BS_PLACING || m_iBuildState == BS_PLACING_INVALID )
+ return true;
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+int C_TFWeaponBuilder::GetSlot( void ) const
+{
+ return GetObjectInfo( m_iObjectType )->m_SelectionSlot;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+int C_TFWeaponBuilder::GetPosition( void ) const
+{
+ return GetObjectInfo( m_iObjectType )->m_SelectionPosition;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void C_TFWeaponBuilder::SetupObjectSelectionSprite( void )
+{
+#ifdef CLIENT_DLL
+ // Use the sprite details from the text file, with a custom sprite
+ char *iconTexture = GetObjectInfo( m_iObjectType )->m_pIconActive;
+ if ( iconTexture && iconTexture[ 0 ] )
+ {
+ m_pSelectionTextureActive = gHUD.GetIcon( iconTexture );
+ }
+ else
+ {
+ m_pSelectionTextureActive = NULL;
+ }
+
+ iconTexture = GetObjectInfo( m_iObjectType )->m_pIconInactive;
+ if ( iconTexture && iconTexture[ 0 ] )
+ {
+ m_pSelectionTextureInactive = gHUD.GetIcon( iconTexture );
+ }
+ else
+ {
+ m_pSelectionTextureInactive = NULL;
+ }
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CHudTexture const *C_TFWeaponBuilder::GetSpriteActive( void ) const
+{
+ return m_pSelectionTextureActive;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CHudTexture const *C_TFWeaponBuilder::GetSpriteInactive( void ) const
+{
+ return m_pSelectionTextureInactive;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Output : char const
+//-----------------------------------------------------------------------------
+const char *C_TFWeaponBuilder::GetPrintName( void ) const
+{
+ return GetObjectInfo( m_iObjectType )->m_AltModes[m_iObjectMode].pszStatusName;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+int C_TFWeaponBuilder::GetSubType( void )
+{
+ return m_iObjectType;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return true if this weapon can be selected via the weapon selection
+//-----------------------------------------------------------------------------
+bool C_TFWeaponBuilder::CanBeSelected( void )
+{
+ CTFPlayer *pOwner = ToTFPlayer( GetOwner() );
+ if ( !pOwner )
+ return false;
+
+ if ( pOwner->CanBuild( m_iObjectType, m_iObjectMode ) != CB_CAN_BUILD )
+ return false;
+
+ return HasAmmo();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return true if this weapon should be visible in the weapon selection
+//-----------------------------------------------------------------------------
+bool C_TFWeaponBuilder::VisibleInWeaponSelection( void )
+{
+ if ( BaseClass::VisibleInWeaponSelection() == false )
+ return false;
+ if ( m_iObjectType != BUILDER_INVALID_OBJECT )
+ return GetObjectInfo( m_iObjectType )->m_bVisibleInWeaponSelection;
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Return true if this weapon has some ammo
+//-----------------------------------------------------------------------------
+bool C_TFWeaponBuilder::HasAmmo( void )
+{
+ CTFPlayer *pOwner = ToTFPlayer( GetOwner() );
+ if ( !pOwner )
+ return false;
+
+ int iCost = pOwner->m_Shared.CalculateObjectCost( pOwner, m_iObjectType );
+ return ( pOwner->GetBuildResources() >= iCost );
+}
+
+// -----------------------------------------------------------------------------
+// Purpose:
+// -----------------------------------------------------------------------------
+bool C_TFWeaponBuilder::CanBuildObjectType( int iObjectType )
+{
+ if ( iObjectType < 0 || iObjectType >= OBJ_LAST )
+ return false;
+
+ return m_aBuildableObjectTypes[iObjectType];
+}
+
+// -----------------------------------------------------------------------------
+// Purpose:
+// -----------------------------------------------------------------------------
+void C_TFWeaponBuilder::UpdateAttachmentModels( void )
+{
+ if ( m_iObjectType != BUILDER_INVALID_OBJECT && GetObjectInfo( m_iObjectType )->m_bUseItemInfo )
+ {
+ BaseClass::UpdateAttachmentModels();
+ }
+}
+
+// -----------------------------------------------------------------------------
+// Purpose:
+// -----------------------------------------------------------------------------
+const char *C_TFWeaponBuilder::GetViewModel( int iViewModel ) const
+{
+ if ( GetPlayerOwner() == NULL )
+ {
+ return BaseClass::GetViewModel();
+ }
+
+ if ( m_iObjectType != BUILDER_INVALID_OBJECT )
+ {
+ if ( GetObjectInfo( m_iObjectType )->m_bUseItemInfo )
+ return BaseClass::GetViewModel();
+
+ return GetObjectInfo( m_iObjectType )->m_pViewModel;
+ }
+
+ return BaseClass::GetViewModel();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+const char *C_TFWeaponBuilder::GetWorldModel( void ) const
+{
+ if ( GetPlayerOwner() == NULL )
+ {
+ return BaseClass::GetWorldModel();
+ }
+
+ if ( m_iObjectType != BUILDER_INVALID_OBJECT )
+ {
+ return GetObjectInfo( m_iObjectType )->m_pPlayerModel;
+ }
+
+ return BaseClass::GetWorldModel();
+}
+
+Activity C_TFWeaponBuilder::GetDrawActivity( void )
+{
+ // sapper used to call different draw animations , one when invis and one when not.
+ // now you can go invis *while* deploying, so let's always use the one-handed deploy.
+ if ( GetType() == OBJ_ATTACHMENT_SAPPER )
+ {
+ return ACT_VM_DRAW_DEPLOYED;
+ }
+
+ return BaseClass::GetDrawActivity();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool C_TFWeaponBuilder::EffectMeterShouldFlash( void )
+{
+ if ( !GetOwner() )
+ return false;
+
+ int iRoboSapper = 0;
+ CALL_ATTRIB_HOOK_INT_ON_OTHER( GetOwner(), iRoboSapper, robo_sapper );
+
+ return ( iRoboSapper && GetEffectBarProgress() >= 1.f );
+}
+
+const char *C_TFWeaponSapper::GetViewModel( int iViewModel ) const
+{
+ // Skip over Builder's version
+ return C_TFWeaponBase::GetViewModel();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+const char *C_TFWeaponSapper::GetWorldModel( void ) const
+{
+ // Skip over Builder's version
+ return C_TFWeaponBase::GetWorldModel();
+}