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/tf2/tf_func_resource.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/server/tf2/tf_func_resource.cpp')
| -rw-r--r-- | game/server/tf2/tf_func_resource.cpp | 683 |
1 files changed, 683 insertions, 0 deletions
diff --git a/game/server/tf2/tf_func_resource.cpp b/game/server/tf2/tf_func_resource.cpp new file mode 100644 index 0000000..cfb0d74 --- /dev/null +++ b/game/server/tf2/tf_func_resource.cpp @@ -0,0 +1,683 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +#include "cbase.h" +#include "EntityOutput.h" +#include "EntityList.h" +#include "tf_player.h" +#include "tf_func_resource.h" +#include "tf_team.h" +#include "tf_basecombatweapon.h" +#include "gamerules.h" +#include "ammodef.h" +#include "tf_obj.h" +#include "resource_chunk.h" +#include "vstdlib/random.h" +#include "engine/IEngineSound.h" +#include "team_messages.h" +#include "tf_stats.h" + +LINK_ENTITY_TO_CLASS( trigger_resourcezone, CResourceZone); + +BEGIN_DATADESC( CResourceZone ) + + // keys + DEFINE_KEYFIELD_NOT_SAVED( m_nResourcesLeft, FIELD_INTEGER, "ResourceAmount" ), + DEFINE_KEYFIELD_NOT_SAVED( m_iMaxChunks, FIELD_INTEGER, "ResourceChunks" ), + DEFINE_KEYFIELD_NOT_SAVED( m_flResourceRate, FIELD_FLOAT, "ResourceRate" ), + DEFINE_KEYFIELD_NOT_SAVED( m_flChunkValueMin, FIELD_FLOAT, "ChunkValueMin" ), + DEFINE_KEYFIELD_NOT_SAVED( m_flChunkValueMax, FIELD_FLOAT, "ChunkValueMax" ), + + // inputs + DEFINE_INPUTFUNC( FIELD_INTEGER, "SetAmount", InputSetAmount ), + DEFINE_INPUTFUNC( FIELD_VOID, "ResetAmount", InputResetAmount ), + DEFINE_INPUTFUNC( FIELD_VOID, "SetActive", InputSetActive ), + DEFINE_INPUTFUNC( FIELD_VOID, "SetInactive", InputSetInactive ), + DEFINE_INPUTFUNC( FIELD_VOID, "ToggleActive", InputToggleActive ), + + // outputs + DEFINE_OUTPUT( m_OnEmpty, "OnEmpty" ), + +END_DATADESC() + + +IMPLEMENT_SERVERCLASS_ST(CResourceZone, DT_ResourceZone) + SendPropFloat( SENDINFO( m_flClientResources ), 8, SPROP_UNSIGNED, 0.0f, 1.0f ), + SendPropInt( SENDINFO( m_nResourcesLeft ), 20, SPROP_UNSIGNED ), +END_SEND_TABLE(); + +PRECACHE_REGISTER( trigger_resourcezone ); + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CResourceZone::CResourceZone() +{ +#ifdef _DEBUG + m_vecGatherPoint.Init(); + m_angGatherPoint.Init(); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: Initializes the resource zone +//----------------------------------------------------------------------------- +void CResourceZone::Spawn( void ) +{ + SetSolid( SOLID_BSP ); + AddSolidFlags( FSOLID_TRIGGER ); + SetMoveType( MOVETYPE_NONE ); + AddEffects( EF_NODRAW ); + SetModel( STRING( GetModelName() ) ); + + if ( !m_nResourcesLeft ) + { + m_nResourcesLeft = 10000; + } + + m_nMaxResources = m_nResourcesLeft; + m_flClientResources = 1; + + SetActive( false ); + m_vecGatherPoint = WorldSpaceCenter(); + m_angGatherPoint = vec3_angle; + m_iTeamGathering = -1; + m_aSpawners.Purge(); + m_hResourcePump = NULL; + + if ( !m_iMaxChunks ) + m_iMaxChunks = 5; + if ( !m_flChunkValueMin ) + m_flChunkValueMin = 20; + if ( !m_flChunkValueMax ) + m_flChunkValueMax = 60; + + m_flBaseResourceRate = m_flResourceRate; + + m_flRespawnTimeModifier = 1.0f; + + m_flTestTime = 0; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CResourceZone::Precache( void ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: See if we've got a gather point specified +//----------------------------------------------------------------------------- +void CResourceZone::Activate( void ) +{ + BaseClass::Activate(); + + if (m_target != NULL_STRING) + { + CBaseEntity *pEnt = gEntList.FindEntityByName( NULL, m_target ); + if ( pEnt ) + { + m_vecGatherPoint = pEnt->GetLocalOrigin(); + m_angGatherPoint = pEnt->GetLocalAngles(); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CResourceZone::InputSetAmount( inputdata_t &inputdata ) +{ + m_nMaxResources = m_nResourcesLeft = inputdata.value.Int(); + RecomputeClientResources(); + + // We may have just been reactivated + if ( m_nResourcesLeft ) + { + SetActive( true ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CResourceZone::InputResetAmount( inputdata_t &inputdata ) +{ + m_nResourcesLeft = m_nMaxResources; + m_flClientResources = 1; + + // We may have just been reactivated + if ( m_nResourcesLeft ) + { + SetActive( true ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CResourceZone::InputSetActive( inputdata_t &inputdata ) +{ + SetActive( true ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CResourceZone::InputSetInactive( inputdata_t &inputdata ) +{ + SetActive( false ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CResourceZone::InputToggleActive( inputdata_t &inputdata ) +{ + if ( GetActive() ) + { + SetActive( false ); + } + else + { + SetActive( true ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CResourceZone::SetActive( bool bActive ) +{ + // Going active? + if ( !m_bActive && bActive ) + { + // Start our ambient sound + //EmitAmbientSound( this, Center(), "ResourceZone.AmbientActiveSound" ); + } + else if ( m_bActive && !bActive ) + { + // Going inactive + + // Stop our sound loop + //StopSound( "ResourceZone.AmbientActiveSound" ); + } + + m_bActive = bActive; + + // Tell all my spawners + for ( int i = 0; i < m_aSpawners.Size(); i++ ) + { + m_aSpawners[i]->SetActive( bActive ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CResourceZone::GetActive() const +{ + return m_bActive; +} + +//----------------------------------------------------------------------------- +// Zone increasing.... +//----------------------------------------------------------------------------- +void CResourceZone::AddZoneIncreaser( float rate ) +{ + Assert( rate != 0.0f ); + + m_flRespawnTimeModifier *= rate; + m_flResourceRate = m_flBaseResourceRate / m_flRespawnTimeModifier; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CResourceZone::RemoveZoneIncreaser( float rate ) +{ + Assert( rate != 0.0f ); + + m_flRespawnTimeModifier /= rate; + m_flResourceRate = m_flBaseResourceRate / m_flRespawnTimeModifier; +} + +//----------------------------------------------------------------------------- +// Purpose: Removes resources from the zone, and returns true if it's now empty +//----------------------------------------------------------------------------- +bool CResourceZone::RemoveResources( int nResourcesRemoved ) +{ + if ( IsEmpty() ) + return true; + + m_nResourcesLeft = MAX(0, m_nResourcesLeft - nResourcesRemoved); + RecomputeClientResources(); + + // If I'm out of resources, destroy my resource spawners + if ( IsEmpty() ) + { + // Tell all existing chunks to stay forever + int i; + for ( i = 0; i < m_aChunks.Size(); i++ ) + { + // Clear them removal think + m_aChunks[i]->SetThink( NULL ); + } + + SetActive( false ); + + // Tell teams about it + for ( i = 0; i < GetNumberOfTeams(); i++ ) + { + CTFTeam *pTeam = GetGlobalTFTeam( i ); + pTeam->PostMessage( TEAMMSG_RESOURCE_ZONE_EMPTIED ); + } + + // Fire my output + m_OnEmpty.FireOutput( NULL,this ); + return true; + } + + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: Return true if this zone is empty +//----------------------------------------------------------------------------- +bool CResourceZone::IsEmpty( void ) +{ + // Inactive zones pretend to be empty, so nothing tries to do anything with them + if ( !GetActive() ) + return true; + + return (m_nResourcesLeft <= 0); +} + +//----------------------------------------------------------------------------- +// Purpose: Return true if the specified point is within this zone +//----------------------------------------------------------------------------- +bool CResourceZone::PointIsWithin( const Vector &vecPoint ) +{ + return CollisionProp()->IsPointInBounds( vecPoint ); +} + +//----------------------------------------------------------------------------- +// Purpose: Resource zones have 1 build point +//----------------------------------------------------------------------------- +int CResourceZone::GetNumBuildPoints( void ) const +{ + return 1; +} + +//----------------------------------------------------------------------------- +// Purpose: Return true if the specified object type can be built on this point +//----------------------------------------------------------------------------- +bool CResourceZone::CanBuildObjectOnBuildPoint( int iPoint, int iObjectType ) +{ + ASSERT( iPoint <= GetNumBuildPoints() ); + + // Don't allow more than one pump + if ( m_hResourcePump.Get() ) + return false; + + // Only pumps can be built on zones + return ( iObjectType == OBJ_RESOURCEPUMP ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CResourceZone::GetBuildPoint( int iPoint, Vector &vecOrigin, QAngle &vecAngles ) +{ + ASSERT( iPoint <= GetNumBuildPoints() ); + + // If we have a gather point, return it + if ( m_vecGatherPoint != WorldSpaceCenter() ) + { + vecOrigin = m_vecGatherPoint; + } + else if ( m_aSpawners.Size() ) + { + // Return the first resource spawner + vecOrigin = m_aSpawners[0]->GetAbsOrigin(); + } + else + { + vecOrigin = GetAbsOrigin(); + } + + vecAngles = QAngle(0,0,0); + return true; +} + +int CResourceZone::GetBuildPointAttachmentIndex( int iPoint ) const +{ + return 0; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CResourceZone::SetObjectOnBuildPoint( int iPoint, CBaseObject *pObject ) +{ + m_hResourcePump = pObject; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int CResourceZone::GetNumObjectsOnMe( void ) +{ + if ( m_hResourcePump.Get() ) + return 1; + + return 0; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CBaseEntity *CResourceZone::GetFirstObjectOnMe( void ) +{ + return m_hResourcePump; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CBaseObject *CResourceZone::GetObjectOfTypeOnMe( int iObjectType ) +{ + if ( GetNumObjectsOnMe() == 1 ) + { + CBaseObject *pObject = dynamic_cast<CBaseObject*>( m_hResourcePump.Get() ); + if ( pObject ) + { + if ( pObject->GetType() == iObjectType ) + return pObject; + } + } + + return NULL; +} + +int CResourceZone::FindObjectOnBuildPoint( CBaseObject *pObject ) +{ + if (m_hResourcePump == pObject) + return 0; + return -1; +} + +void CResourceZone::GetExitPoint( CBaseEntity *pPlayer, int iPoint, Vector *pAbsOrigin, QAngle *pAbsAngles ) +{ + Assert(0); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CResourceZone::RemoveAllObjects( void ) +{ + UTIL_Remove( m_hResourcePump ); +} + +//----------------------------------------------------------------------------- +// Purpose: Get the team that's gathering from this point +//----------------------------------------------------------------------------- +CTFTeam *CResourceZone::GetOwningTeam( void ) +{ + if ( m_iTeamGathering == -1 ) + return NULL; + + return (CTFTeam*)GetGlobalTeam(m_iTeamGathering); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CResourceZone::SetOwningTeam( int iTeamNumber ) +{ + m_iTeamGathering = iTeamNumber; +} + +//----------------------------------------------------------------------------- +// Purpose: Transmit this to all players who are in commander mode +//----------------------------------------------------------------------------- +int CResourceZone::ShouldTransmit( const CCheckTransmitInfo *pInfo ) +{ + // Team rules may tell us that we should + CBaseEntity* pRecipientEntity = CBaseEntity::Instance( pInfo->m_pClientEnt ); + Assert( pRecipientEntity->IsPlayer() ); + + CBasePlayer *pPlayer = (CBasePlayer*)pRecipientEntity; + if ( pPlayer->GetTeam() ) + { + if (pPlayer->GetTeam()->ShouldTransmitToPlayer( pPlayer, this )) + return FL_EDICT_ALWAYS; + } + + return FL_EDICT_DONTSEND; +} + +//----------------------------------------------------------------------------- +// Purpose: Check to see if we should create any more resource chunks +//----------------------------------------------------------------------------- +bool CResourceZone::ShouldSpawnChunk( void ) +{ + // Don't spawn chunks if we're outta resources + if ( IsEmpty() ) + return false; + + // Create a chunk if we're below our max + if ( m_aChunks.Size() >= m_iMaxChunks ) + return false; + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CResourceZone::SpawnChunk( const Vector &vecOrigin ) +{ + // ROBIN: Disabled for now + return; + + TFStats()->IncrementStat( TF_STAT_RESOURCE_CHUNKS_SPAWNED, 1 ); + + // Create a resource chunk and add it to our list + Vector vecVelocity = Vector( random->RandomFloat( -100,100 ), random->RandomFloat( -100,100 ), random->RandomFloat( 300,600 )); + CResourceChunk *pChunk = CResourceChunk::Create( false, vecOrigin, vecVelocity ); + pChunk->m_hZone = this; + + // Add it to our list + m_aChunks.AddToTail( pChunk ); + + // Remove it's value from the zone + RemoveResources( pChunk->GetResourceValue() ); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CResourceZone::RecomputeClientResources( ) +{ + m_flClientResources = clamp( (float)m_nResourcesLeft / (float)m_nMaxResources, 0.0f, 1.0f ); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CResourceZone::RemoveChunk( CResourceChunk *pChunk, bool bReturn ) +{ + if (bReturn) + { + TFStats()->IncrementStat( TF_STAT_RESOURCE_CHUNKS_RETIRED, 1 ); + } + + m_aChunks.FindAndRemove( pChunk ); + + // If I'm being returned, re-add my value to the resource level of the zone + if ( bReturn ) + { + m_nResourcesLeft += pChunk->GetResourceValue(); + RecomputeClientResources(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CResourceZone::AddSpawner( CResourceSpawner *pSpawner ) +{ + m_aSpawners.AddToTail( pSpawner ); + pSpawner->SetActive( GetActive() ); +} + +//======================================================================================================================== +// RESOURCE CHUNK SPAWNER +//======================================================================================================================== +LINK_ENTITY_TO_CLASS( env_resourcespawner, CResourceSpawner ); +PRECACHE_REGISTER( env_resourcespawner ); + +BEGIN_DATADESC( CResourceSpawner ) + + // functions + DEFINE_FUNCTION( SpawnChunkThink ), + +END_DATADESC() + + +IMPLEMENT_SERVERCLASS_ST(CResourceSpawner, DT_ResourceSpawner) + SendPropInt( SENDINFO( m_bActive ), 1, SPROP_UNSIGNED ), +END_SEND_TABLE(); + +// Resource Spawner Models +char *sResourceSpawnerModel = "models/resources/resource_spawner_B.mdl"; + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CResourceSpawner::Spawn( void ) +{ + m_hZone = NULL; + m_bActive = false; + SetModel( sResourceSpawnerModel ); + + // Create the object in the physics system + /* + VPhysicsInitStatic(); + */ + SetMoveType( MOVETYPE_NONE ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CResourceSpawner::Precache( void ) +{ + PrecacheModel( sResourceSpawnerModel ); +} + +//----------------------------------------------------------------------------- +// Purpose: Find my resource point +//----------------------------------------------------------------------------- +void CResourceSpawner::Activate( void ) +{ + if ( m_target != NULL_STRING ) + { + // Find my resource zone + CResourceZone *pZone = (CResourceZone*)gEntList.FindEntityByName( NULL, m_target ); + if ( pZone ) + { + m_hZone = pZone; + SetModel( sResourceSpawnerModel ); + m_hZone->AddSpawner( this ); + return; + } + } + + Warning( "ERROR: Resource Spawner without a target resource zone specified.\n" ); + UTIL_Remove( this ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CResourceSpawner::SetActive( bool bActive ) +{ + // Going active? + if ( !m_bActive && bActive ) + { + // Randomize the thinks a little to reduce network usage ong chunk spawning + SetNextThink( gpGlobals->curtime + m_hZone->GetResourceRate() + random->RandomFloat( 0.0, 1.0 ) ); + SetThink( SpawnChunkThink ); + RemoveEffects( EF_NODRAW ); + } + else if ( m_bActive && !bActive ) + { + // Going inactive + SetThink( NULL ); + AddEffects( EF_NODRAW ); + } + + m_bActive = bActive; +} + +//----------------------------------------------------------------------------- +// Purpose: Spawn a chunk from this spawner +//----------------------------------------------------------------------------- +void CResourceSpawner::SpawnChunkThink( void ) +{ + // Lost our zone? + if ( !m_hZone ) + { + SetActive( false ); + return; + } + + if ( m_hZone->ShouldSpawnChunk() ) + { + // Start spawning events + EntityMessageBegin( this ); + MessageEnd(); + + m_hZone->SpawnChunk( GetAbsOrigin() + Vector(0,0,64) ); + } + + // Randomize the thinks a little to reduce network usage on chunk spawning + SetNextThink( gpGlobals->curtime + m_hZone->GetResourceRate() + random->RandomFloat( 0.0, 1.0 ) ); +} + +//----------------------------------------------------------------------------- +// Purpose: Convert an amount of resources into a number of processed & unprocessed resource chunks +//----------------------------------------------------------------------------- +void ConvertResourceValueToChunks( int iResources, int *iNumProcessed, int *iNumNormal ) +{ + *iNumProcessed = *iNumNormal = 0; + + while ( iResources >= resource_chunk_processed_value.GetFloat() ) + { + iResources -= resource_chunk_processed_value.GetFloat(); + *iNumProcessed += 1; + } + + while ( iResources >= resource_chunk_value.GetFloat() ) + { + iResources -= resource_chunk_value.GetFloat(); + *iNumNormal += 1; + } + + // Round up + if ( iResources ) + { + *iNumNormal++; + } +}
\ No newline at end of file |