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/server/gameweaponmanager.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/server/gameweaponmanager.cpp')
| -rw-r--r-- | game/server/gameweaponmanager.cpp | 290 |
1 files changed, 290 insertions, 0 deletions
diff --git a/game/server/gameweaponmanager.cpp b/game/server/gameweaponmanager.cpp new file mode 100644 index 0000000..68bced8 --- /dev/null +++ b/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(); +} |