diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/client/tf/c_obj_dispenser.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/client/tf/c_obj_dispenser.cpp')
| -rw-r--r-- | game/client/tf/c_obj_dispenser.cpp | 393 |
1 files changed, 393 insertions, 0 deletions
diff --git a/game/client/tf/c_obj_dispenser.cpp b/game/client/tf/c_obj_dispenser.cpp new file mode 100644 index 0000000..169aa58 --- /dev/null +++ b/game/client/tf/c_obj_dispenser.cpp @@ -0,0 +1,393 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Client's CObjectSentrygun +// +// $NoKeywords: $ +//=============================================================================// +#include "cbase.h" +#include "c_baseobject.h" +#include "c_tf_player.h" +#include "vgui/ILocalize.h" +#include "c_obj_dispenser.h" + +// NVNT haptics system interface +#include "c_tf_haptics.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +using namespace vgui; + +//----------------------------------------------------------------------------- +// Purpose: RecvProxy that converts the Team's player UtlVector to entindexes +//----------------------------------------------------------------------------- +void RecvProxy_HealingList( const CRecvProxyData *pData, void *pStruct, void *pOut ) +{ + C_ObjectDispenser *pDispenser = (C_ObjectDispenser*)pStruct; + + CBaseHandle *pHandle = (CBaseHandle*)(&(pDispenser->m_hHealingTargets[pData->m_iElement])); + RecvProxy_IntToEHandle( pData, pStruct, pHandle ); + + // update the heal beams + pDispenser->m_bUpdateHealingTargets = true; +} + +void RecvProxyArrayLength_HealingArray( void *pStruct, int objectID, int currentArrayLength ) +{ + C_ObjectDispenser *pDispenser = (C_ObjectDispenser*)pStruct; + + if ( pDispenser->m_hHealingTargets.Size() != currentArrayLength ) + pDispenser->m_hHealingTargets.SetSize( currentArrayLength ); + + // update the heal beams + pDispenser->m_bUpdateHealingTargets = true; +} + +//----------------------------------------------------------------------------- +// Purpose: Dispenser object +//----------------------------------------------------------------------------- + +IMPLEMENT_CLIENTCLASS_DT(C_ObjectDispenser, DT_ObjectDispenser, CObjectDispenser) + RecvPropInt( RECVINFO( m_iState ) ), + RecvPropInt( RECVINFO( m_iAmmoMetal ) ), + RecvPropInt( RECVINFO( m_iMiniBombCounter ) ), + + RecvPropArray2( + RecvProxyArrayLength_HealingArray, + RecvPropInt( "healing_array_element", 0, SIZEOF_IGNORE, 0, RecvProxy_HealingList ), + MAX_PLAYERS, + 0, + "healing_array" + ) +END_RECV_TABLE() + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +C_ObjectDispenser::C_ObjectDispenser() +{ + m_bUpdateHealingTargets = false; + m_bPlayingSound = false; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +C_ObjectDispenser::~C_ObjectDispenser() +{ + StopSound( "Building_Dispenser.Heal" ); + // NVNT see if local player is in the list of targets + // temp. fix if dispener is destroyed will stop all healers. + if(m_bPlayingSound) + { + if(tfHaptics.healingDispenserCount>0) { + tfHaptics.healingDispenserCount --; + if(tfHaptics.healingDispenserCount==0 && !tfHaptics.wasBeingHealedMedic) + tfHaptics.isBeingHealed = false; + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : updateType - +//----------------------------------------------------------------------------- +void C_ObjectDispenser::OnDataChanged( DataUpdateType_t updateType ) +{ + BaseClass::OnDataChanged( updateType ); + +#ifdef STAGING_ONLY + if ( updateType == DATA_UPDATE_CREATED ) + { + SetNextClientThink( CLIENT_THINK_ALWAYS ); + } +#endif // STAGING_ONLY + + if ( m_bUpdateHealingTargets ) + { + UpdateEffects(); + m_bUpdateHealingTargets = false; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_ObjectDispenser::ClientThink() +{ + BaseClass::ClientThink(); + +#ifdef STAGING_ONLY + C_TFPlayer *pTFOwner = GetOwner(); + if ( pTFOwner && pTFOwner->m_Shared.IsEnteringOrExitingFullyInvisible() ) + { + UpdateEffects(); + } +#endif // STAGING_ONLY +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_ObjectDispenser::SetInvisibilityLevel( float flValue ) +{ + if ( IsEnteringOrExitingFullyInvisible( flValue ) ) + { + UpdateEffects(); + } + + BaseClass::SetInvisibilityLevel( flValue ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_ObjectDispenser::UpdateEffects( void ) +{ + C_TFPlayer *pOwner = GetOwner(); + + if ( GetInvisibilityLevel() == 1.f || ( pOwner && pOwner->m_Shared.IsFullyInvisible() ) ) + { + StopEffects( true ); + return; + } + + StopEffects(); + + // Now add any new targets + for ( int i = 0; i < m_hHealingTargets.Count(); i++ ) + { + C_BaseEntity *pTarget = m_hHealingTargets[i].Get(); + + // Loops through the healing targets, and make sure we have an effect for each of them + if ( pTarget ) + { + // don't want to show this effect for stealthed spies + C_TFPlayer *pPlayer = dynamic_cast< C_TFPlayer * >( pTarget ); + if ( pPlayer && ( pPlayer->m_Shared.IsStealthed() || pPlayer->m_Shared.InCond( TF_COND_STEALTHED_BLINK ) ) ) + continue; + + bool bHaveEffect = false; + for ( int targets = 0; targets < m_hHealingTargetEffects.Count(); targets++ ) + { + if ( m_hHealingTargetEffects[targets].pTarget == pTarget ) + { + bHaveEffect = true; + break; + } + } + + if ( bHaveEffect ) + continue; + // NVNT if the dispenser has started to heal the local player + // notify the haptics system + if(pTarget==C_BasePlayer::GetLocalPlayer()) + { + tfHaptics.healingDispenserCount++; + if(!tfHaptics.wasBeingHealedMedic) { + tfHaptics.isBeingHealed = true; + } + } + + const char *pszEffectName; + if ( GetTeamNumber() == TF_TEAM_RED ) + { + pszEffectName = "dispenser_heal_red"; + } + else + { + pszEffectName = "dispenser_heal_blue"; + } + + CNewParticleEffect *pEffect; + + // if we don't have a model, attach at the origin, otherwise use attachment 'heal_origin' + if ( FBitSet( GetObjectFlags(), OF_DOESNT_HAVE_A_MODEL ) ) + { + // offset the origin to player's chest + if ( FBitSet( GetObjectFlags(), OF_PLAYER_DESTRUCTION ) ) + { + pEffect = ParticleProp()->Create( pszEffectName, PATTACH_ABSORIGIN_FOLLOW, NULL, Vector( 0, 0, 50 ) ); + } + else + { + pEffect = ParticleProp()->Create( pszEffectName, PATTACH_ABSORIGIN_FOLLOW ); + } + } + else + { + pEffect = ParticleProp()->Create( pszEffectName, PATTACH_POINT_FOLLOW, "heal_origin" ); + } + + ParticleProp()->AddControlPoint( pEffect, 1, pTarget, PATTACH_ABSORIGIN_FOLLOW, NULL, Vector(0,0,50) ); + + int iIndex = m_hHealingTargetEffects.AddToTail(); + m_hHealingTargetEffects[iIndex].pTarget = pTarget; + m_hHealingTargetEffects[iIndex].pEffect = pEffect; + + // Start the sound over again every time we start a new beam + StopSound( "Building_Dispenser.Heal" ); + + CLocalPlayerFilter filter; + EmitSound( filter, entindex(), "Building_Dispenser.Heal" ); + + m_bPlayingSound = true; + } + } + + // Stop the sound if we're not healing anyone + if ( m_bPlayingSound && m_hHealingTargets.Count() == 0 ) + { + m_bPlayingSound = false; + + // stop the sound + StopSound( "Building_Dispenser.Heal" ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_ObjectDispenser::StopEffects( bool bRemoveAll /* = false */ ) +{ + // Find all the targets we've stopped healing + bool bStillHealing[MAX_DISPENSER_HEALING_TARGETS] = { 0 }; + for ( int i = 0; i < m_hHealingTargetEffects.Count(); i++ ) + { + bStillHealing[i] = false; + + // Are we still healing this target? + if ( !bRemoveAll ) + { + for ( int target = 0; target < m_hHealingTargets.Count(); target++ ) + { + if ( m_hHealingTargets[target] && m_hHealingTargets[target] == m_hHealingTargetEffects[i].pTarget ) + { + bStillHealing[i] = true; + break; + } + } + } + } + + // Now remove all the dead effects + for ( int i = m_hHealingTargetEffects.Count()-1; i >= 0; i-- ) + { + if ( !bStillHealing[i] ) + { + + // NVNT if the healing target of this dispenser is the local player. + // inform the haptics system interface we are no longer healing. + if(m_hHealingTargetEffects[i].pTarget==C_BasePlayer::GetLocalPlayer()) + { + if(tfHaptics.healingDispenserCount>0) { + tfHaptics.healingDispenserCount --; + if(tfHaptics.healingDispenserCount==0 && !tfHaptics.wasBeingHealedMedic) + tfHaptics.isBeingHealed = false; + } + } + + ParticleProp()->StopEmission( m_hHealingTargetEffects[i].pEffect ); + m_hHealingTargetEffects.Remove(i); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: Damage level has changed, update our effects +//----------------------------------------------------------------------------- +void C_ObjectDispenser::UpdateDamageEffects( BuildingDamageLevel_t damageLevel ) +{ + if ( m_hDamageEffects ) + { + m_hDamageEffects->StopEmission( false, false ); + m_hDamageEffects = NULL; + } + + const char *pszEffect = ""; + + switch( damageLevel ) + { + case BUILDING_DAMAGE_LEVEL_LIGHT: + pszEffect = "dispenserdamage_1"; + break; + case BUILDING_DAMAGE_LEVEL_MEDIUM: + pszEffect = "dispenserdamage_2"; + break; + case BUILDING_DAMAGE_LEVEL_HEAVY: + pszEffect = "dispenserdamage_3"; + break; + case BUILDING_DAMAGE_LEVEL_CRITICAL: + pszEffect = "dispenserdamage_4"; + break; + + default: + break; + } + + if ( Q_strlen(pszEffect) > 0 ) + { + m_hDamageEffects = ParticleProp()->Create( pszEffect, PATTACH_ABSORIGIN ); + } +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +int C_ObjectDispenser::GetMaxMetal( void ) +{ + return DISPENSER_MAX_METAL_AMMO; +} + +//----------------------------------------------------------------------------- +// Control screen +//----------------------------------------------------------------------------- + +DECLARE_VGUI_SCREEN_FACTORY( CDispenserControlPanel, "screen_obj_dispenser_blue" ); +DECLARE_VGUI_SCREEN_FACTORY( CDispenserControlPanel_Red, "screen_obj_dispenser_red" ); + +//----------------------------------------------------------------------------- +// Constructor: +//----------------------------------------------------------------------------- +CDispenserControlPanel::CDispenserControlPanel( vgui::Panel *parent, const char *panelName ) +: BaseClass( parent, "CDispenserControlPanel" ) +{ + m_pAmmoProgress = new RotatingProgressBar( this, "MeterArrow" ); +} + +//----------------------------------------------------------------------------- +// Deactivates buttons we can't afford +//----------------------------------------------------------------------------- +void CDispenserControlPanel::OnTickActive( C_BaseObject *pObj, C_TFPlayer *pLocalPlayer ) +{ + BaseClass::OnTickActive( pObj, pLocalPlayer ); + + Assert( dynamic_cast< C_ObjectDispenser* >( pObj ) ); + m_hDispenser = static_cast< C_ObjectDispenser* >( pObj ); + + float flProgress = m_hDispenser ? m_hDispenser->GetMetalAmmoCount() / (float)m_hDispenser->GetMaxMetal() : 0.f; + + m_pAmmoProgress->SetProgress( flProgress ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CDispenserControlPanel::IsVisible( void ) +{ + if ( m_hDispenser ) + { +#ifdef STAGING_ONLY + if ( m_hDispenser->IsMiniBuilding() ) + return false; +#endif // STAGING_ONLY + + if ( m_hDispenser->GetInvisibilityLevel() == 1.f ) + return false; + } + + return BaseClass::IsVisible(); +} + +IMPLEMENT_CLIENTCLASS_DT(C_ObjectCartDispenser, DT_ObjectCartDispenser, CObjectCartDispenser) +END_RECV_TABLE()
\ No newline at end of file |