summaryrefslogtreecommitdiff
path: root/game/shared/tf/tf_condition.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/shared/tf/tf_condition.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'game/shared/tf/tf_condition.cpp')
-rw-r--r--game/shared/tf/tf_condition.cpp397
1 files changed, 397 insertions, 0 deletions
diff --git a/game/shared/tf/tf_condition.cpp b/game/shared/tf/tf_condition.cpp
new file mode 100644
index 0000000..084c1d0
--- /dev/null
+++ b/game/shared/tf/tf_condition.cpp
@@ -0,0 +1,397 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Condition Objects
+//
+//=============================================================================
+
+#include "cbase.h"
+#include "tf_condition.h"
+
+#ifdef GAME_DLL
+#include "tf_player.h"
+#else
+#include "c_tf_player.h"
+#include "achievementmgr.h"
+#include "baseachievement.h"
+#include "achievements_tf.h"
+#endif
+
+#ifdef CLIENT_DLL
+
+BEGIN_PREDICTION_DATA_NO_BASE( CTFConditionList )
+DEFINE_PRED_FIELD( _condition_bits, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ),
+END_PREDICTION_DATA()
+
+BEGIN_RECV_TABLE_NOBASE( CTFConditionList, DT_TFPlayerConditionListExclusive )
+RecvPropInt( RECVINFO( _condition_bits ) ),
+END_RECV_TABLE()
+
+#else
+
+BEGIN_SEND_TABLE_NOBASE( CTFConditionList, DT_TFPlayerConditionListExclusive )
+SendPropInt( SENDINFO( _condition_bits ), MIN( TF_COND_LAST, 32 ), SPROP_UNSIGNED ),
+END_SEND_TABLE()
+
+#endif
+
+//-----------------------------------------------------------------------------
+// Ctor
+//-----------------------------------------------------------------------------
+CTFConditionList::CTFConditionList()
+{
+ _condition_bits = _old_condition_bits = 0;
+}
+
+//-----------------------------------------------------------------------------
+// Condition factory.
+//-----------------------------------------------------------------------------
+bool CTFConditionList::Add( ETFCond type, float duration, CTFPlayer* outer, CBaseEntity* provider /*= NULL*/ )
+{
+#ifdef GAME_DLL
+ return _Add( type, duration, outer, provider );
+#else
+ return type == TF_COND_CRITBOOSTED;
+#endif
+}
+
+bool CTFConditionList::_Add( ETFCond type, float duration, CTFPlayer* outer, CBaseEntity* provider /*= NULL*/ )
+{
+ // If we already have a condition of this type, ask it to handle the addition of another.
+ for ( int i = 0; i < _conditions.Count(); ++i )
+ {
+ if ( _conditions[i]->GetType() == type )
+ {
+ _conditions[i]->Add( duration );
+ _conditions[i]->SetProvider( provider );
+ return true;
+ }
+ }
+
+ // Add a new condition.
+ CTFCondition* newCond = NULL;
+ switch ( type )
+ {
+ // TODO: Register new conditions anonymously instead of switching.
+ case TF_COND_CRITBOOSTED:
+ newCond = new CTFCondition_CritBoost( type, duration, outer, provider );
+ break;
+ }
+
+ if ( newCond )
+ {
+ _condition_bits |= (1<<type);
+ _old_condition_bits |= (1<<type);
+
+ _conditions.AddToTail( newCond );
+ newCond->OnAdded();
+ newCond->SetProvider( provider );
+
+ return true;
+ }
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Remove a condition from the player.
+//-----------------------------------------------------------------------------
+bool CTFConditionList::Remove( ETFCond type, bool ignore_duration )
+{
+#ifdef GAME_DLL
+ bool bConditionListHandledRemoval = _Remove( type, ignore_duration );
+
+ // The condition list only handles one type of condition. Written slightly weird
+ // to avoid unused variable warnings with asserts disabled.
+ if ( bConditionListHandledRemoval )
+ {
+ Assert( type == TF_COND_CRITBOOSTED );
+ }
+#endif
+ return type == TF_COND_CRITBOOSTED;
+}
+
+bool CTFConditionList::_Remove( ETFCond type, bool ignore_duration )
+{
+ for ( int i=_conditions.Count()-1; i>=0; --i )
+ {
+ CTFCondition* cond = _conditions[i];
+ if ( !cond || cond->GetType() != type )
+ continue;
+
+ if ( cond->UsesMinDuration() && !ignore_duration && cond->GetMinDuration() > 0 )
+ {
+ cond->SetMaxDuration( cond->GetMinDuration() );
+ continue; // Can't remove conditions that haven't expired.
+ }
+
+ _conditions.Remove( i );
+
+ _condition_bits &= ~(1<<type);
+ _old_condition_bits &= ~(1<<type);
+
+ cond->OnRemoved();
+ delete cond;
+
+ return true;
+ }
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Clear all conditions from the player.
+//-----------------------------------------------------------------------------
+void CTFConditionList::RemoveAll()
+{
+ _condition_bits = 0;
+ _old_condition_bits = 0;
+
+ for ( int i=0; i<_conditions.Count(); ++i )
+ {
+ _conditions[i]->OnRemoved();
+ }
+ _conditions.PurgeAndDeleteElements();
+}
+
+//-----------------------------------------------------------------------------
+// Checks if we have at least one of a given condition applied.
+//-----------------------------------------------------------------------------
+bool CTFConditionList::InCond( ETFCond type ) const
+{
+ return ( ( _condition_bits & (1<<type) ) != 0 );
+}
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+CBaseEntity *CTFConditionList::GetProvider( ETFCond type ) const
+{
+ CBaseEntity *pProvider = NULL;
+ for ( int i = 0; i < _conditions.Count(); ++i )
+ {
+ if ( _conditions[i]->GetType() == type )
+ {
+ pProvider = _conditions[i]->GetProvider();
+ break;
+ }
+ }
+
+ return pProvider;
+}
+
+//-----------------------------------------------------------------------------
+// Client/Server periodic condition think.
+//-----------------------------------------------------------------------------
+void CTFConditionList::Think()
+{
+ for ( int i=0; i<_conditions.Count(); ++i )
+ {
+ _conditions[i]->OnThink();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Server only per-frame think.
+//-----------------------------------------------------------------------------
+void CTFConditionList::ServerThink()
+{
+#ifdef GAME_DLL
+ for ( int i=0; i<_conditions.Count(); ++i )
+ {
+ CTFCondition* cond = _conditions[i];
+ if ( cond->GetMaxDuration() > PERMANENT_CONDITION ||
+ cond->GetMinDuration() > PERMANENT_CONDITION )
+ {
+ // Reduce the duration over time.
+ float reduction = gpGlobals->frametime;
+
+ // Healable conditions expire faster when we have healers.
+ int numHealers = cond->GetOuter()->m_Shared.GetNumHealers();
+ if ( cond->IsHealable() && numHealers > 0 )
+ {
+ reduction += numHealers * reduction * 4;
+ }
+
+ // Decrement min duration.
+ if ( cond->GetMinDuration() > PERMANENT_CONDITION )
+ {
+ cond->SetMinDuration( MAX( cond->GetMinDuration() - reduction, 0 ) );
+ }
+
+ // Decrement max duration.
+ if ( cond->GetMaxDuration() > PERMANENT_CONDITION )
+ {
+ cond->SetMaxDuration( MAX( cond->GetMaxDuration() - reduction, 0 ) );
+
+ if ( cond->GetMaxDuration() < cond->GetMinDuration() )
+ {
+ cond->SetMaxDuration( cond->GetMinDuration() );
+ }
+ }
+
+ if ( cond->GetMaxDuration() == 0 )
+ {
+ Remove( cond->GetType() );
+ continue;
+ }
+ }
+
+ _conditions[i]->OnServerThink();
+ }
+#endif
+}
+
+#ifdef CLIENT_DLL
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+void CTFConditionList::OnPreDataChanged( void )
+{
+// _old_condition_bits = _condition_bits;
+}
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+void CTFConditionList::OnDataChanged( CTFPlayer* outer )
+{
+ // Is there a way to improve this by hooking directly into network state changed?
+ if ( _old_condition_bits != _condition_bits )
+ {
+ UpdateClientConditions( outer );
+
+ _old_condition_bits = _condition_bits;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Creates or destroys conditions to make sure our state matches the server.
+//-----------------------------------------------------------------------------
+void CTFConditionList::UpdateClientConditions( CTFPlayer* outer )
+{
+ int nCondChanged = _condition_bits ^ _old_condition_bits;
+ int nCondAdded = nCondChanged & _condition_bits;
+ int nCondRemoved = nCondChanged & _old_condition_bits;
+
+ int i;
+ for ( i=0;i<TF_COND_LAST;i++ )
+ {
+ if ( nCondAdded & (1<<i) )
+ {
+ _Add( (ETFCond)i, PERMANENT_CONDITION, outer );
+ }
+ else if ( nCondRemoved & (1<<i) )
+ {
+ _Remove( (ETFCond)i );
+ }
+ }
+}
+
+#endif
+
+//-----------------------------------------------------------------------------
+// Ctor
+//-----------------------------------------------------------------------------
+CTFCondition::CTFCondition( ETFCond type, float duration, CTFPlayer* outer, CBaseEntity* provider /*= NULL*/ )
+: _type( type ),
+ _min_duration( 0 ),
+ _max_duration( duration ),
+ _outer( outer ),
+ _provider( provider )
+{
+}
+
+//-----------------------------------------------------------------------------
+// Dtor
+//-----------------------------------------------------------------------------
+CTFCondition::~CTFCondition()
+{
+}
+
+//-----------------------------------------------------------------------------
+// Called if we try to add another condition of a type we already have.
+//-----------------------------------------------------------------------------
+void CTFCondition::Add( float duration )
+{
+ if ( duration != PERMANENT_CONDITION )
+ {
+ // If our new duration is not permanent, is shorter than
+ // our current duration, and is longer than our min duration
+ // make it our new min duration.
+ if ( GetMaxDuration() == PERMANENT_CONDITION ||
+ duration < GetMaxDuration() )
+ {
+ if ( duration > GetMinDuration() )
+ SetMinDuration( duration );
+
+ return;
+ }
+ }
+ else if ( GetMaxDuration() != PERMANENT_CONDITION )
+ {
+ // If our current duration is not permanent and we are adding a
+ // permanent duration, make our old finite duration the new min duration.
+ // This ensures we last at least that long.
+ SetMinDuration( GetMaxDuration() );
+ }
+
+ SetMaxDuration( duration );
+}
+
+//=============================================================================
+// Crit Boost
+//=============================================================================
+CTFCondition_CritBoost::CTFCondition_CritBoost( ETFCond type, float duration, CTFPlayer* outer, CBaseEntity* provider /*= NULL*/ )
+: CTFCondition( type, duration, outer, provider )
+{
+ Assert( type == TF_COND_CRITBOOSTED );
+}
+
+void CTFCondition_CritBoost::OnAdded()
+{
+#ifdef CLIENT_DLL
+ GetOuter()->m_Shared.UpdateCritBoostEffect();
+
+ if ( GetOuter()->IsLocalPlayer() && GetOuter()->IsPlayerClass( TF_CLASS_HEAVYWEAPONS ) )
+ {
+ g_AchievementMgrTF.OnAchievementEvent( ACHIEVEMENT_TF_HEAVY_RECEIVE_UBER_GRIND );
+ }
+#endif
+}
+
+void CTFCondition_CritBoost::OnRemoved()
+{
+#ifdef CLIENT_DLL
+ GetOuter()->m_Shared.UpdateCritBoostEffect();
+#endif
+}
+
+void CTFCondition_CritBoost::OnThink()
+{
+#ifdef CLIENT_DLL
+ if ( GetOuter()->m_pCritBoostEffect )
+ {
+ CBaseEntity *pWeapon = NULL;
+ // Use GetRenderedWeaponModel() instead?
+ if ( GetOuter()->IsLocalPlayer() )
+ {
+ pWeapon = GetOuter()->GetViewModel(0);
+ }
+ else
+ {
+ pWeapon = GetOuter()->GetActiveWeapon();
+ }
+
+ // Transfer the crit boosted effect if we've switched weapons
+ if ( GetOuter()->m_pCritBoostEffect->GetOwner() != pWeapon )
+ {
+ GetOuter()->m_Shared.UpdateCritBoostEffect();
+ }
+ }
+#endif
+}
+
+void CTFCondition_CritBoost::OnServerThink()
+{
+}