//========= Copyright Valve Corporation, All rights reserved. ============// // // Weapons. // // CTFWeaponBase // | // |--> CTFWeaponBaseMelee // | | // | |--> CTFWeaponCrowbar // | |--> CTFWeaponKnife // | |--> CTFWeaponMedikit // | |--> CTFWeaponWrench // | // |--> CTFWeaponBaseGrenade // | | // | |--> CTFWeapon // | |--> CTFWeapon // | // |--> CTFWeaponBaseGun // //============================================================================= #ifndef TF_WEAPONBASE_H #define TF_WEAPONBASE_H #ifdef _WIN32 #pragma once #endif #include "tf_playeranimstate.h" #include "tf_weapon_parse.h" #include "npcevent.h" #include "ihasowner.h" #include "tf_item_wearable.h" // Client specific. #if defined( CLIENT_DLL ) #define CTFWeaponBase C_TFWeaponBase #define CTFWeaponAttachmentModel C_TFWeaponAttachmentModel #define CTFWeaponBaseGrenadeProj C_TFWeaponBaseGrenadeProj #include "tf_fx_muzzleflash.h" #include "GameEventListener.h" #endif #define MAX_TRACER_NAME 128 class CTFPlayer; class CBaseObject; class CTFWeaponBaseGrenadeProj; class CTFWeaponAttachmentModel; // Given an ammo type (like from a weapon's GetPrimaryAmmoType()), this compares it // against the ammo name you specify. // TFTODO: this should use indexing instead of searching and strcmp()'ing all the time. bool IsAmmoType( int iAmmoType, const char *pAmmoName ); void FindHullIntersection( const Vector &vecSrc, trace_t &tr, const Vector &mins, const Vector &maxs, CBaseEntity *pEntity ); // Reloading singly. enum { TF_RELOAD_START = 0, TF_RELOADING, TF_RELOADING_CONTINUE, TF_RELOAD_FINISH }; // structure to encapsulate state of head bob struct BobState_t { BobState_t() { m_flBobTime = 0; m_flLastBobTime = 0; m_flLastSpeed = 0; m_flVerticalBob = 0; m_flLateralBob = 0; } float m_flBobTime; float m_flLastBobTime; float m_flLastSpeed; float m_flVerticalBob; float m_flLateralBob; }; enum EWeaponStrangeType_t { STRANGE_UNKNOWN = -1, STRANGE_NOT_STRANGE = 0, STRANGE_IS_STRANGE = 1, }; enum EWeaponStatTrakModuleType_t { MODULE_UNKNOWN = -1, MODULE_NONE = 0, MODULE_FOUND = 1, }; #ifdef CLIENT_DLL float CalcViewModelBobHelper( CBasePlayer *player, BobState_t *pBobState ); void AddViewModelBobHelper( Vector &origin, QAngle &angles, BobState_t *pBobState ); #endif // Interface for weapons that have a charge time class ITFChargeUpWeapon { public: virtual bool CanCharge( void ) = 0; virtual float GetChargeBeginTime( void ) = 0; virtual float GetChargeMaxTime( void ) = 0; virtual float GetCurrentCharge( void ) { return ( gpGlobals->curtime - GetChargeBeginTime() ) / GetChargeMaxTime(); } }; class CTraceFilterIgnoreTeammates : public CTraceFilterSimple { public: // It does have a base, but we'll never network anything below here.. DECLARE_CLASS( CTraceFilterIgnoreTeammates, CTraceFilterSimple ); CTraceFilterIgnoreTeammates( const IHandleEntity *passentity, int collisionGroup, int iIgnoreTeam ) : CTraceFilterSimple( passentity, collisionGroup ), m_iIgnoreTeam( iIgnoreTeam ) { } virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask ) { CBaseEntity *pEntity = EntityFromEntityHandle( pServerEntity ); if ( ( pEntity->IsPlayer() || pEntity->IsCombatItem() ) && ( pEntity->GetTeamNumber() == m_iIgnoreTeam || m_iIgnoreTeam == TEAM_ANY ) ) { return false; } return BaseClass::ShouldHitEntity( pServerEntity, contentsMask ); } int m_iIgnoreTeam; }; class CTraceFilterIgnorePlayers : public CTraceFilterSimple { public: // It does have a base, but we'll never network anything below here.. DECLARE_CLASS( CTraceFilterIgnorePlayers, CTraceFilterSimple ); CTraceFilterIgnorePlayers( const IHandleEntity *passentity, int collisionGroup ) : CTraceFilterSimple( passentity, collisionGroup ) { } virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask ) { CBaseEntity *pEntity = EntityFromEntityHandle( pServerEntity ); if ( pEntity && pEntity->IsPlayer() ) return false; return BaseClass::ShouldHitEntity( pServerEntity, contentsMask ); } }; class CTraceFilterIgnoreFriendlyCombatItems : public CTraceFilterSimple { public: DECLARE_CLASS( CTraceFilterIgnoreFriendlyCombatItems, CTraceFilterSimple ); CTraceFilterIgnoreFriendlyCombatItems( const IHandleEntity *passentity, int collisionGroup, int iIgnoreTeam, bool bIsProjectile = false ) : CTraceFilterSimple( passentity, collisionGroup ), m_iIgnoreTeam( iIgnoreTeam ) { m_bCallerIsProjectile = bIsProjectile; } virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask ) { CBaseEntity *pEntity = EntityFromEntityHandle( pServerEntity ); // if ( ( pEntity->MyCombatCharacterPointer() || pEntity->MyCombatWeaponPointer() ) && pEntity->GetTeamNumber() == m_iIgnoreTeam ) // return false; // // if ( pEntity->IsPlayer() && pEntity->GetTeamNumber() == m_iIgnoreTeam ) // return false; if ( pEntity->IsCombatItem() ) { if ( pEntity->GetTeamNumber() == m_iIgnoreTeam ) return false; // If source is a enemy projectile, be explicit, otherwise we fail a "IsTransparent" test downstream if ( m_bCallerIsProjectile ) return true; } return BaseClass::ShouldHitEntity( pServerEntity, contentsMask ); } int m_iIgnoreTeam; bool m_bCallerIsProjectile; }; #define ENERGY_WEAPON_MAX_CHARGE 20 #define TF_PARTICLE_WEAPON_BLUE_1 Vector( 0.345, 0.52, 0.635 ) #define TF_PARTICLE_WEAPON_BLUE_2 Vector( 0.145, 0.427, 0.55 ) #define TF_PARTICLE_WEAPON_RED_1 Vector( 0.72, 0.22, 0.23 ) #define TF_PARTICLE_WEAPON_RED_2 Vector( 0.5, 0.18, 0.125 ) //============================================================================= // // Base TF Weapon Class // #if defined( CLIENT_DLL ) class CTFWeaponBase : public CBaseCombatWeapon, public IHasOwner, public CGameEventListener #else class CTFWeaponBase : public CBaseCombatWeapon, public IHasOwner #endif { DECLARE_CLASS( CTFWeaponBase, CBaseCombatWeapon ); DECLARE_NETWORKCLASS(); DECLARE_PREDICTABLE(); #if !defined ( CLIENT_DLL ) DECLARE_DATADESC(); #endif // Setup. CTFWeaponBase(); ~CTFWeaponBase(); virtual void Spawn(); virtual void Activate( void ); virtual void Precache(); virtual bool IsPredicted() const { return true; } virtual void FallInit( void ); // Weapon Data. CTFWeaponInfo const &GetTFWpnData() const; virtual int GetWeaponID( void ) const; bool IsWeapon( int iWeapon ) const; virtual int GetDamageType() const { return g_aWeaponDamageTypes[ GetWeaponID() ]; } virtual int GetCustomDamageType() const { return TF_DMG_CUSTOM_NONE; } virtual int GetMaxClip1( void ) const; virtual int GetDefaultClip1( void ) const; virtual bool UsesPrimaryAmmo(); virtual float UberChargeAmmoPerShot( void ) { float fAmmo = 0; CALL_ATTRIB_HOOK_FLOAT( fAmmo, ubercharge_ammo ); return fAmmo * 0.01f; } virtual int Clip1() { return IsEnergyWeapon() ? Energy_GetEnergy() : m_iClip1; } virtual int Clip2() { return m_iClip2; } virtual bool HasAmmo( void ); // View model. virtual const char *GetViewModel( int iViewModel = 0 ) const; virtual const char *GetWorldModel( void ) const; virtual bool SendWeaponAnim( int iActivity ) OVERRIDE; virtual CBaseEntity *GetOwnerViaInterface( void ) { return GetOwner(); } virtual void Equip( CBaseCombatCharacter *pOwner ); virtual void Drop( const Vector &vecVelocity ); virtual void UpdateOnRemove( void ); virtual bool CanHolster( void ) const; virtual bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); virtual bool Deploy( void ); virtual bool ForceWeaponSwitch() const OVERRIDE; virtual void Detach( void ); virtual void OnActiveStateChanged( int iOldState ); virtual bool OwnerCanJump( void ) { return true; } virtual bool VisibleInWeaponSelection( void ); virtual void UpdateHands( void ); virtual bool OwnerCanTaunt( void ) { return true; } virtual bool CanBeCritBoosted( void ); bool CanHaveRevengeCrits( void ); // Extra wearables. #ifdef GAME_DLL virtual void ChangeTeam( int iTeamNum ) OVERRIDE; virtual void UpdateExtraWearables(); virtual void ExtraWearableEquipped( CTFWearable *pExtraWearableItem ); virtual void ExtraWearableViewModelEquipped( CTFWearable *pExtraWearableItem ); virtual bool HideAttachmentsAndShowBodygroupsWhenPerformingWeaponIndependentTaunt() const { return true; } #endif // GAME_DLL virtual void RemoveExtraWearables( void ); // Attacks. virtual void Misfire( void ); virtual void FireFullClipAtOnce( void ); virtual void PrimaryAttack(); virtual void SecondaryAttack(); void CalcIsAttackCritical( void ); virtual bool CalcIsAttackCriticalHelper(); virtual bool CalcIsAttackCriticalHelperNoCrits(); bool IsCurrentAttackACrit() const { return m_bCurrentAttackIsCrit; } bool IsCurrentAttackARandomCrit() const { return m_bCurrentAttackIsCrit && m_bCurrentCritIsRandom; } bool IsCurrentAttackDuringDemoCharge() const { return m_bCurrentAttackIsDuringDemoCharge; } virtual ETFDmgCustom GetPenetrateType() const; virtual void GetProjectileFireSetup( CTFPlayer *pPlayer, Vector vecOffset, Vector *vecSrc, QAngle *angForward, bool bHitTeammates = true, float flEndDist = 2000.f ); virtual QAngle GetSpreadAngles( void ); float GetLastPrimaryAttackTime( void ) const { return m_flLastPrimaryAttackTime; } virtual bool CanPerformSecondaryAttack() const OVERRIDE; virtual bool IsFiring( void ) const { return false; } virtual bool AreRandomCritsEnabled( void ); // Reloads. virtual bool Reload( void ); virtual void AbortReload( void ); virtual bool DefaultReload( int iClipSize1, int iClipSize2, int iActivity ); void SendReloadEvents(); virtual bool IsReloading() const; // is the weapon reloading right now? virtual bool AutoFiresFullClip( void ) const OVERRIDE; bool AutoFiresFullClipAllAtOnce( void ) const; bool CanOverload( void ) const; virtual bool CheckReloadMisfire( void ) { return false; } virtual bool CanDrop( void ) { return false; } virtual bool AllowTaunts( void ) { return true; } // Fire Rate float ApplyFireDelay( float flDelay ) const; // Sound. bool PlayEmptySound(); bool IsSilentKiller(); // Activities. virtual void ItemBusyFrame( void ); virtual void ItemPostFrame( void ); virtual void ItemHolsterFrame( void ); virtual void SetWeaponVisible( bool visible ); virtual int GetActivityWeaponRole() const; virtual acttable_t *ActivityList( int &iActivityCount ) OVERRIDE; virtual Activity TranslateViewmodelHandActivityInternal( Activity actBase ); virtual int GetViewModelWeaponRole() { return GetTFWpnData().m_iWeaponType; } #ifdef GAME_DLL virtual void AddAssociatedObject( CBaseObject *pObject ) { } virtual void RemoveAssociatedObject( CBaseObject *pObject ) { } virtual void ApplyOnHitAttributes( CBaseEntity *pVictimBaseEntity, CTFPlayer *pAttacker, const CTakeDamageInfo &info ); virtual void ApplyPostHitEffects( const CTakeDamageInfo &inputInfo, CTFPlayer *pPlayer ); virtual void ApplyOnInjuredAttributes( CTFPlayer *pVictim, CTFPlayer *pAttacker, const CTakeDamageInfo &info ); // when owner of this weapon is hit virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); virtual bool DeflectProjectiles(); virtual bool DeflectPlayer( CTFPlayer *pTarget, CTFPlayer *pOwner, Vector &vecForward, Vector &vecCenter, Vector &vecSize ); virtual bool DeflectEntity( CBaseEntity *pTarget, CTFPlayer *pOwner, Vector &vecForward, Vector &vecCenter, Vector &vecSize ); static void SendObjectDeflectedEvent( CTFPlayer *pNewOwner, CTFPlayer *pPrevOwner, int iWeaponID, CBaseAnimating *pObject ); static float DeflectionForce( const Vector &size, float damage, float scale ); virtual void PlayDeflectionSound( bool bPlayer ) {} virtual Vector GetDeflectionSize() { return Vector( 128, 128, 64 ); } virtual float GetJarateTime() { return 0.f; } void ApplyItemRegen( void ); kill_eater_event_t GetKillEaterKillEventType() const; #endif // Utility. CBasePlayer *GetPlayerOwner() const; CTFPlayer *GetTFPlayerOwner() const; #ifdef CLIENT_DLL virtual bool ShouldPlayClientReloadSound() { return false; } C_BaseEntity *GetWeaponForEffect(); virtual const char* ModifyEventParticles( const char* token ) { return token; } // Shadows virtual ShadowType_t ShadowCastType( void ) OVERRIDE; #endif virtual bool CanAttack(); virtual int GetCanAttackFlags() const { return TF_CAN_ATTACK_FLAG_NONE; } // Raising & Lowering for grenade throws bool WeaponShouldBeLowered( void ); virtual bool Ready( void ); virtual bool Lower( void ); virtual void WeaponIdle( void ); virtual void WeaponReset( void ); virtual void WeaponRegenerate( void ); // Muzzleflashes virtual const char *GetMuzzleFlashEffectName_3rd( void ) { return NULL; } virtual const char *GetMuzzleFlashEffectName_1st( void ) { return NULL; } virtual const char *GetMuzzleFlashModel( void ); virtual float GetMuzzleFlashModelLifetime( void ); virtual const char *GetMuzzleFlashParticleEffect( void ); virtual const char *GetTracerType( void ); virtual void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); // CEconEntity virtual const char *GetInventoryModel( void ); virtual void ReapplyProvision( void ); virtual float GetSpeedMod( void ) { return 1.f; }; virtual bool CanFireCriticalShot( bool bIsHeadshot = false ); virtual bool CanFireRandomCriticalShot( float flCritChance ); virtual char const *GetShootSound( int iIndex ) const; void UpdateHiddenParentBodygroup( bool bHide ); virtual void OnControlStunned( void ); virtual bool HideWhileStunned( void ) { return true; } virtual bool IsViewModelFlipped( void ); virtual int GetMaxHealthMod() { return 0; } virtual float GetLastDeployTime( void ) { return m_flLastDeployTime; } // Energy Weapons virtual bool IsEnergyWeapon( void ) const { return false; } virtual bool IsBlastImpactWeapon( void ) const { return false; } float Energy_GetMaxEnergy( void ) const; float Energy_GetEnergy( void ) const { return m_flEnergy; } void Energy_SetEnergy( float flEnergy ) { m_flEnergy = flEnergy; } bool Energy_FullyCharged( void ) const; bool Energy_HasEnergy( void ); void Energy_DrainEnergy( void ); void Energy_DrainEnergy( float flDrain ); bool Energy_Recharge( void ); virtual float Energy_GetShotCost( void ) const { return 4.f; } virtual float Energy_GetRechargeCost( void ) const { return 4.f; } virtual Vector GetParticleColor( int iColor ); virtual void CheckReload( void ); virtual void FinishReload( void ); virtual bool HasLastShotCritical( void ) { return false; } virtual bool UseServerRandomSeed( void ) const { return true; } // Server specific. #if !defined( CLIENT_DLL ) // Spawning. virtual void CheckRespawn(); virtual CBaseEntity* Respawn(); void Materialize(); void AttemptToMaterialize(); // Death. void Die( void ); void SetDieThink( bool bDie ); // Disguise weapon. void DisguiseWeaponThink( void ); // Ammo. virtual const Vector& GetBulletSpread(); // Hit tracking for achievements // Track the number of kills we've had since we missed. Only works for bullet firing weapons right now. virtual void OnBulletFire( int iEnemyPlayersHit ); virtual void OnPlayerKill( CTFPlayer *pVictim, const CTakeDamageInfo &info ); virtual float GetLastHitTime( void ) { return m_flLastHitTime; } virtual int GetDropSkinOverride( void ) { return -1; } int GetKillStreak () const { return m_iKillStreak; } void SetKillStreak ( int value ) { m_iKillStreak = value; }; float GetClipScale () const { return m_flClipScale; } void SetClipScale ( float flScale ) { m_flClipScale = flScale; } // Client specific. #else bool IsFirstPersonView(); bool UsingViewModel(); C_BaseAnimating *GetAppropriateWorldOrViewModel(); virtual bool ShouldDraw( void ) OVERRIDE; virtual void UpdateVisibility( void ) OVERRIDE; virtual void ProcessMuzzleFlashEvent( void ); virtual void DispatchMuzzleFlash( const char* effectName, C_BaseEntity* pAttachEnt ); virtual int InternalDrawModel( int flags ); virtual bool ShouldPredict(); virtual void PostDataUpdate( DataUpdateType_t updateType ); virtual void OnDataChanged( DataUpdateType_t type ); virtual void OnPreDataChanged( DataUpdateType_t updateType ); virtual int GetWorldModelIndex( void ); virtual bool ShouldDrawCrosshair( void ); virtual void Redraw( void ); virtual void FireGameEvent( IGameEvent *event ); virtual void AddViewmodelBob( CBaseViewModel *viewmodel, Vector &origin, QAngle &angles ); virtual float CalcViewmodelBob( void ); BobState_t *GetBobState(); virtual bool AttachmentModelsShouldBeVisible( void ) OVERRIDE { return (m_iState == WEAPON_IS_ACTIVE) && !IsBeingRepurposedForTaunt(); } virtual bool ShouldEjectBrass() { return true; } bool OnFireEvent( C_BaseViewModel *pViewModel, const Vector& origin, const QAngle& angles, int event, const char *options ); // ItemEffect Hud defaults virtual const char * GetEffectLabelText() { return ""; } virtual float GetProgress() { return 0; } // Model muzzleflashes CHandle m_hMuzzleFlashModel[2]; bool IsUsingOverrideModel() const { return m_iWorldModelIndex != m_iCachedModelIndex; } #endif virtual int GetSkin(); static void UpdateWeaponBodyGroups( CTFPlayer* pPlayer, bool bHandleDeployedBodygroups ); void SetIsBeingRepurposedForTaunt( bool bCanOverride ) { m_bBeingRepurposedForTaunt = bCanOverride; } bool IsBeingRepurposedForTaunt() const { return m_bBeingRepurposedForTaunt; } int GetKillComboClass( void ) const { return m_nKillComboClass; } int GetKillComboCount( void ) const { return m_nKillComboCount; } void ClearKillComboCount( void ) { m_nKillComboCount = 0; } void AddKillCombo( int nClassKilled ) { if ( m_nKillComboClass != nClassKilled ) { m_nKillComboClass = nClassKilled; ClearKillComboCount(); } m_nKillComboCount = Min( 3, m_nKillComboCount + 1 ); } // Effect / Regeneration bar handling virtual float GetEffectBarProgress( void ); // Get the current bar state (will return a value from 0.0 to 1.0) bool HasEffectBarRegeneration( void ) { return InternalGetEffectBarRechargeTime() > 0; } // Check the base, not modified by attribute, because attrib may have reduced it to 0. float GetEffectBarRechargeTime( void ) { float flTime = InternalGetEffectBarRechargeTime(); CALL_ATTRIB_HOOK_FLOAT( flTime, effectbar_recharge_rate ); return flTime; } void DecrementBarRegenTime( float flTime ) { m_flEffectBarRegenTime -= flTime; } bool IsHonorBound( void ) const; virtual bool CanPickupOtherWeapon() const { return true; } EWeaponStrangeType_t GetStrangeType(); bool BHasStatTrakModule(); #ifdef CLIENT_DLL // StatTrak View Model Test void UpdateAllViewmodelAddons( void ); void AddStatTrakModel( CEconItemView *pItem, int nStatTrakType, AccountID_t holderAcctId ); void RemoveViewmodelStatTrak( void ); void RemoveWorldmodelStatTrak( void ); CHandle< CTFWeaponAttachmentModel > m_viewmodelStatTrakAddon; CHandle< CTFWeaponAttachmentModel > m_worldmodelStatTrakAddon; virtual const Vector& GetViewmodelOffset() OVERRIDE; #endif virtual bool ShouldRemoveInvisibilityOnPrimaryAttack() const { return true; } protected: virtual int GetEffectBarAmmo( void ) { return m_iPrimaryAmmoType; } virtual float InternalGetEffectBarRechargeTime( void ) { return 0; } // Time it takes for this regeneration bar to fully recharge from 0 to full. void StartEffectBarRegen( void ); // Call this when you want your bar to start recharging (usually when you've deployed your action) void EffectBarRegenFinished( void ); void CheckEffectBarRegen( void ); private: CNetworkVar( float, m_flEffectBarRegenTime ); // The time Regen is scheduled to complete protected: #ifdef CLIENT_DLL virtual void CreateMuzzleFlashEffects( C_BaseEntity *pAttachEnt, int nIndex ); virtual void UpdateExtraWearablesVisibility(); #endif // CLIENT_DLL // Reloads. void UpdateReloadTimers( bool bStart ); void SetReloadTimer( float flReloadTime ); bool ReloadSingly( void ); void ReloadSinglyPostFrame( void ); void IncrementAmmo( void ); bool NeedsReloadForAmmo1( int iClipSize1 ) const; bool NeedsReloadForAmmo2( int iClipSize2 ) const; protected: void PlayUpgradedShootSound( const char *pszSound ); int m_iWeaponMode; CNetworkVar( int, m_iReloadMode ); CNetworkVar( float, m_flReloadPriorNextFire ); CTFWeaponInfo *m_pWeaponInfo; bool m_bInAttack; bool m_bInAttack2; bool m_bCurrentAttackIsCrit; bool m_bCurrentCritIsRandom; bool m_bCurrentAttackIsDuringDemoCharge; EWeaponStrangeType_t m_eStrangeType; EWeaponStatTrakModuleType_t m_eStatTrakModuleType; CNetworkVar( bool, m_bLowered ); int m_iAltFireHint; int m_iReloadStartClipAmount; float m_flCritTime; CNetworkVar( float, m_flLastCritCheckTime ); // Deprecated int m_iLastCritCheckFrame; int m_iCurrentSeed; float m_flLastRapidFireCritCheckTime; float m_flLastDeployTime; char m_szTracerName[MAX_TRACER_NAME]; CNetworkVar( bool, m_bResetParity ); int m_iAmmoToAdd; float m_flLastPrimaryAttackTime; #ifdef GAME_DLL // Stores the number of kills we've made since we last shot & didn't hit a player. // Only hooked up to bullet firing right now, so you'll need to do plumbing if you want it for other weaponry. int m_iConsecutiveKills; // Accuracy tracking float m_flLastHitTime; int m_iHitsInTime; int m_iFiredInTime; // Used to generate active-weapon-only regen float m_flRegenTime; // for penetrating weapons with drain - only drain each victim once CHandle< CTFPlayer > m_hLastDrainVictim; CountdownTimer m_lastDrainVictimTimer; int m_iKillStreak; float m_flClipScale; #endif #ifdef CLIENT_DLL bool m_bOldResetParity; int m_iCachedModelIndex; int m_iEjectBrassAttachpoint; #endif CNetworkVar( bool, m_bReloadedThroughAnimEvent ); CNetworkVar( float, m_flEnergy ); public: CNetworkVar( bool, m_bDisguiseWeapon ); CNetworkVar( float, m_flLastFireTime ); CNetworkHandle( CTFWearable, m_hExtraWearable ); CNetworkHandle( CTFWearable, m_hExtraWearableViewModel ); CNetworkVar( float, m_flObservedCritChance ); virtual bool CanInspect() const; void HandleInspect(); enum TFWeaponInspectStage { INSPECT_INVALID = -1, INSPECT_START, INSPECT_IDLE, INSPECT_END, INSPECT_STAGE_COUNT }; TFWeaponInspectStage GetInspectStage() const { return (TFWeaponInspectStage)m_nInspectStage.Get(); } float GetInspectAnimTime() const { return m_flInspectAnimTime; } private: CTFWeaponBase( const CTFWeaponBase & ); CNetworkVar( bool, m_bBeingRepurposedForTaunt ); CNetworkVar( int, m_nKillComboClass ); CNetworkVar( int, m_nKillComboCount ); int GetInspectActivity( TFWeaponInspectStage inspectStage ); bool IsInspectActivity( int iActivity ); CNetworkVar( float, m_flInspectAnimTime ); CNetworkVar( int, m_nInspectStage ); bool m_bInspecting; friend class CTFDroppedWeapon; #ifdef CLIENT_DLL bool m_bInitViewmodelOffset; Vector m_vecViewmodelOffset; #endif // CLIENT_DLL }; bool WeaponID_IsSniperRifle( int iWeaponID ); bool WeaponID_IsSniperRifleOrBow( int iWeaponID ); #define WEAPON_RANDOM_RANGE 10000 #ifdef CLIENT_DLL //----------------------------------------------------------------------------- // CTFWeaponAttachmentModel //----------------------------------------------------------------------------- class CTFWeaponAttachmentModel : public CBaseAnimating, public IHasOwner { DECLARE_CLASS( CTFWeaponAttachmentModel, CBaseAnimating ); public: CTFWeaponAttachmentModel() { m_bIsViewModelAttachment = false; m_hWeaponAssociatedWith = NULL; } virtual bool ShouldDraw( void ); void Init( CBaseEntity *pParent, CTFWeaponBase *pAssociatedWeapon, bool bIsViewModel ); void SetWeaponAssociatedWith( CTFWeaponBase *pWeapon ) { m_hWeaponAssociatedWith = pWeapon; } CBaseEntity* GetWeaponAssociatedWith( void ) const { return m_hWeaponAssociatedWith.Get(); } bool BIsViewModelAttachment() { return m_bIsViewModelAttachment; } virtual CBaseEntity *GetOwnerViaInterface( void ) OVERRIDE { return m_hWeaponAssociatedWith.Get() ? m_hWeaponAssociatedWith.Get()->GetOwner() : NULL; } private: bool m_bIsViewModelAttachment; CHandle< CTFWeaponBase > m_hWeaponAssociatedWith; }; #endif // CLIENT_DLL #endif // TF_WEAPONBASE_H