aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/server/gameweaponmanager.cpp
diff options
context:
space:
mode:
authorJoe Ludwig <[email protected]>2013-06-26 15:22:04 -0700
committerJoe Ludwig <[email protected]>2013-06-26 15:22:04 -0700
commit39ed87570bdb2f86969d4be821c94b722dc71179 (patch)
treeabc53757f75f40c80278e87650ea92808274aa59 /mp/src/game/server/gameweaponmanager.cpp
downloadsource-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz
source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip
First version of the SOurce SDK 2013
Diffstat (limited to 'mp/src/game/server/gameweaponmanager.cpp')
-rw-r--r--mp/src/game/server/gameweaponmanager.cpp290
1 files changed, 290 insertions, 0 deletions
diff --git a/mp/src/game/server/gameweaponmanager.cpp b/mp/src/game/server/gameweaponmanager.cpp
new file mode 100644
index 00000000..b1c7af63
--- /dev/null
+++ b/mp/src/game/server/gameweaponmanager.cpp
@@ -0,0 +1,290 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+#include "cbase.h"
+
+#include "gameweaponmanager.h"
+#include "saverestore_utlvector.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+//=========================================================
+//=========================================================
+class CGameWeaponManager;
+static CUtlVector<CGameWeaponManager *> g_Managers;
+
+
+//=========================================================
+//=========================================================
+class CGameWeaponManager : public CBaseEntity
+{
+ DECLARE_CLASS( CGameWeaponManager, CBaseEntity );
+ DECLARE_DATADESC();
+
+public:
+ void Spawn();
+ CGameWeaponManager()
+ {
+ m_flAmmoMod = 1.0f;
+ m_bExpectingWeapon = false;
+ g_Managers.AddToTail( this );
+ }
+
+ ~CGameWeaponManager()
+ {
+ g_Managers.FindAndRemove( this );
+ }
+
+ void Think();
+ void InputSetMaxPieces( inputdata_t &inputdata );
+ void InputSetAmmoModifier( inputdata_t &inputdata );
+
+ string_t m_iszWeaponName;
+ int m_iMaxPieces;
+ float m_flAmmoMod;
+ bool m_bExpectingWeapon;
+
+ CUtlVector<EHANDLE> m_ManagedNonWeapons;
+
+};
+
+BEGIN_DATADESC( CGameWeaponManager )
+
+//fields
+ DEFINE_KEYFIELD( m_iszWeaponName, FIELD_STRING, "weaponname" ),
+ DEFINE_KEYFIELD( m_iMaxPieces, FIELD_INTEGER, "maxpieces" ),
+ DEFINE_KEYFIELD( m_flAmmoMod, FIELD_FLOAT, "ammomod" ),
+ DEFINE_FIELD( m_bExpectingWeapon, FIELD_BOOLEAN ),
+// funcs
+ DEFINE_FUNCTION( Think ),
+// inputs
+ DEFINE_INPUTFUNC( FIELD_INTEGER, "SetMaxPieces", InputSetMaxPieces ),
+ DEFINE_INPUTFUNC( FIELD_FLOAT, "SetAmmoModifier", InputSetAmmoModifier ),
+
+ DEFINE_UTLVECTOR( m_ManagedNonWeapons, FIELD_EHANDLE ),
+
+END_DATADESC()
+
+LINK_ENTITY_TO_CLASS( game_weapon_manager, CGameWeaponManager );
+
+void CreateWeaponManager( const char *pWeaponName, int iMaxPieces )
+{
+ CGameWeaponManager *pManager = (CGameWeaponManager *)CreateEntityByName( "game_weapon_manager");
+
+ if( pManager )
+ {
+ pManager->m_iszWeaponName = MAKE_STRING( pWeaponName );
+ pManager->m_iMaxPieces = iMaxPieces;
+ DispatchSpawn( pManager );
+ }
+}
+
+void WeaponManager_AmmoMod( CBaseCombatWeapon *pWeapon )
+{
+ for ( int i = 0; i < g_Managers.Count(); i++ )
+ {
+ if ( g_Managers[i]->m_iszWeaponName == pWeapon->m_iClassname )
+ {
+ int iNewClip = (int)(pWeapon->m_iClip1 * g_Managers[i]->m_flAmmoMod);
+ int iNewRandomClip = iNewClip + RandomInt( -2, 2 );
+
+ if ( iNewRandomClip > pWeapon->GetMaxClip1() )
+ {
+ iNewRandomClip = pWeapon->GetMaxClip1();
+ }
+ else if ( iNewRandomClip <= 0 )
+ {
+ //Drop at least one bullet.
+ iNewRandomClip = 1;
+ }
+
+ pWeapon->m_iClip1 = iNewRandomClip;
+ }
+ }
+}
+
+void WeaponManager_AddManaged( CBaseEntity *pWeapon )
+{
+ for ( int i = 0; i < g_Managers.Count(); i++ )
+ {
+ if ( g_Managers[i]->m_iszWeaponName == pWeapon->m_iClassname )
+ {
+ Assert( g_Managers[i]->m_ManagedNonWeapons.Find( pWeapon ) == g_Managers[i]->m_ManagedNonWeapons.InvalidIndex() );
+ g_Managers[i]->m_ManagedNonWeapons.AddToTail( pWeapon );
+ break;
+ }
+ }
+}
+
+void WeaponManager_RemoveManaged( CBaseEntity *pWeapon )
+{
+ for ( int i = 0; i < g_Managers.Count(); i++ )
+ {
+ if ( g_Managers[i]->m_iszWeaponName == pWeapon->m_iClassname )
+ {
+ int j = g_Managers[i]->m_ManagedNonWeapons.Find( pWeapon );
+ if ( j != g_Managers[i]->m_ManagedNonWeapons.InvalidIndex() )
+ {
+ g_Managers[i]->m_ManagedNonWeapons.FastRemove( j );
+ }
+ }
+ }
+}
+
+//---------------------------------------------------------
+//---------------------------------------------------------
+void CGameWeaponManager::Spawn()
+{
+ SetThink( &CGameWeaponManager::Think );
+ SetNextThink( gpGlobals->curtime );
+ CBaseEntity *pEntity = CreateEntityByName( STRING(m_iszWeaponName) );
+ if ( !pEntity )
+ {
+ DevMsg("%s removed itself!\n", GetDebugName() );
+ UTIL_Remove(this);
+ }
+ else
+ {
+ m_bExpectingWeapon = ( dynamic_cast<CBaseCombatWeapon *>(pEntity) != NULL );
+ UTIL_Remove(pEntity);
+ }
+}
+
+//---------------------------------------------------------
+// Count of all the weapons in the world of my type and
+// see if we have a surplus. If there is a surplus, try
+// to find suitable candidates for removal.
+//
+// Right now we just remove the first weapons we find that
+// are behind the player, or are out of the player's PVS.
+// Later, we may want to score the results so that we
+// removed the farthest gun that's not in the player's
+// viewcone, etc.
+//
+// Some notes and thoughts:
+//
+// This code is designed NOT to remove weapons that are
+// hand-placed by level designers. It should only clean
+// up weapons dropped by dead NPCs, which is useful in
+// situations where enemies are spawned in for a sustained
+// period of time.
+//
+// Right now we PREFER to remove weapons that are not in the
+// player's PVS, but this could be opposite of what we
+// really want. We may only want to conduct the cleanup on
+// weapons that are IN the player's PVS.
+//---------------------------------------------------------
+void CGameWeaponManager::Think()
+{
+ int i;
+
+ // Don't have to think all that often.
+ SetNextThink( gpGlobals->curtime + 2.0 );
+
+ const char *pszWeaponName = STRING( m_iszWeaponName );
+
+ CUtlVector<CBaseEntity *> candidates( 0, 64 );
+
+ if ( m_bExpectingWeapon )
+ {
+ CBaseCombatWeapon *pWeapon = NULL;
+ // Firstly, count the total number of weapons of this type in the world.
+ // Also count how many of those can potentially be removed.
+ pWeapon = assert_cast<CBaseCombatWeapon *>(gEntList.FindEntityByClassname( pWeapon, pszWeaponName ));
+
+ while( pWeapon )
+ {
+ if( !pWeapon->IsEffectActive( EF_NODRAW ) && pWeapon->IsRemoveable() )
+ {
+ candidates.AddToTail( pWeapon );
+ }
+
+ pWeapon = assert_cast<CBaseCombatWeapon *>(gEntList.FindEntityByClassname( pWeapon, pszWeaponName ));
+ }
+ }
+ else
+ {
+ for ( i = 0; i < m_ManagedNonWeapons.Count(); i++)
+ {
+ CBaseEntity *pEntity = m_ManagedNonWeapons[i];
+ if ( pEntity )
+ {
+ Assert( pEntity->m_iClassname == m_iszWeaponName );
+ if ( !pEntity->IsEffectActive( EF_NODRAW ) )
+ {
+ candidates.AddToTail( pEntity );
+ }
+ }
+ else
+ {
+ m_ManagedNonWeapons.FastRemove( i-- );
+ }
+ }
+ }
+
+ // Calculate the surplus.
+ int surplus = candidates.Count() - m_iMaxPieces;
+
+ // Based on what the player can see, try to clean up the world by removing weapons that
+ // the player cannot see right at the moment.
+ CBaseEntity *pCandidate;
+ for ( i = 0; i < candidates.Count() && surplus > 0; i++ )
+ {
+ bool fRemovedOne = false;
+
+ pCandidate = candidates[i];
+ Assert( !pCandidate->IsEffectActive( EF_NODRAW ) );
+
+ if ( gpGlobals->maxClients == 1 )
+ {
+ CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
+ // Nodraw serves as a flag that this weapon is already being removed since
+ // all we're really doing inside this loop is marking them for removal by
+ // the entity system. We don't want to count the same weapon as removed
+ // more than once.
+ if( !UTIL_FindClientInPVS( pCandidate->edict() ) )
+ {
+ fRemovedOne = true;
+ }
+ else if( !pPlayer->FInViewCone( pCandidate ) )
+ {
+ fRemovedOne = true;
+ }
+ else if ( UTIL_DistApprox( pPlayer->GetAbsOrigin(), pCandidate->GetAbsOrigin() ) > (30*12) )
+ {
+ fRemovedOne = true;
+ }
+ }
+ else
+ {
+ fRemovedOne = true;
+ }
+
+ if( fRemovedOne )
+ {
+ pCandidate->AddEffects( EF_NODRAW );
+ UTIL_Remove( pCandidate );
+
+ DevMsg( 2, "Surplus %s removed\n", pszWeaponName);
+ surplus--;
+ }
+ }
+}
+
+//---------------------------------------------------------
+//---------------------------------------------------------
+void CGameWeaponManager::InputSetMaxPieces( inputdata_t &inputdata )
+{
+ m_iMaxPieces = inputdata.value.Int();
+}
+
+//---------------------------------------------------------
+//---------------------------------------------------------
+void CGameWeaponManager::InputSetAmmoModifier( inputdata_t &inputdata )
+{
+ m_flAmmoMod = inputdata.value.Float();
+}