aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/shared/env_meteor_shared.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/shared/env_meteor_shared.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/shared/env_meteor_shared.cpp')
-rw-r--r--mp/src/game/shared/env_meteor_shared.cpp399
1 files changed, 399 insertions, 0 deletions
diff --git a/mp/src/game/shared/env_meteor_shared.cpp b/mp/src/game/shared/env_meteor_shared.cpp
new file mode 100644
index 00000000..eedab8a1
--- /dev/null
+++ b/mp/src/game/shared/env_meteor_shared.cpp
@@ -0,0 +1,399 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+#include "cbase.h"
+#include "env_meteor_shared.h"
+#include "mapdata_shared.h"
+#include "sharedInterface.h"
+
+//=============================================================================
+//
+// Meteor Functions.
+//
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+CEnvMeteorShared::CEnvMeteorShared()
+{
+ m_nID = 0;
+ m_vecStartPosition.Init();
+ m_vecDirection.Init();
+ m_flSpeed = 0.0f;
+ m_flDamageRadius = 0.0f;
+ m_flStartTime = METEOR_INVALID_TIME;
+ m_flPassiveTime = METEOR_INVALID_TIME;
+ m_flWorldEnterTime = METEOR_INVALID_TIME;
+ m_flWorldExitTime = METEOR_INVALID_TIME;
+ m_nLocation = METEOR_LOCATION_INVALID;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CEnvMeteorShared::Init( int nID, float flStartTime, float flPassiveTime,
+ const Vector &vecStartPosition,
+ const Vector &vecDirection, float flSpeed, float flDamageRadius,
+ const Vector &vecTriggerMins, const Vector &vecTriggerMaxs )
+{
+ // Setup initial parametric state.
+ m_nID = nID;
+ VectorCopy( vecStartPosition, m_vecStartPosition );
+ VectorCopy( vecStartPosition, m_vecPos );
+ VectorCopy( vecDirection, m_vecDirection );
+ m_flSpeed = flSpeed;
+ m_flDamageRadius = flDamageRadius;
+ m_flStartTime = flPassiveTime + flStartTime;
+ m_flPassiveTime = flPassiveTime;
+ m_flPosTime = m_flStartTime;
+
+ // Calculate the enter/exit times.
+ CalcEnterAndExitTimes( vecTriggerMins, vecTriggerMaxs );
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CEnvMeteorShared::GetPositionAtTime( float flTime, Vector &vecPosition )
+{
+ float flDeltaTime = flTime - m_flPosTime;
+ Vector vecVelocity( m_vecDirection.x * m_flSpeed, m_vecDirection.y * m_flSpeed, m_vecDirection.z * m_flSpeed );
+ VectorMA( m_vecPos, flDeltaTime, vecVelocity, vecPosition );
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CEnvMeteorShared::ConvertFromSkyboxToWorld( void )
+{
+ // The new start position is the position at which the meteor enters
+ // the skybox.
+ Vector vecSkyboxOrigin;
+ g_pMapData->Get3DSkyboxOrigin( vecSkyboxOrigin );
+ float flSkyboxScale = g_pMapData->Get3DSkyboxScale();
+
+ m_vecPos += ( m_flSpeed * m_vecDirection ) * ( m_flWorldEnterTime - m_flStartTime );
+ m_vecPos -= vecSkyboxOrigin;
+ m_vecPos *= flSkyboxScale;
+
+ // Scale the speed.
+ m_flSpeed *= flSkyboxScale;
+
+ // Reset the start time.
+ m_flPosTime = m_flWorldEnterTime;
+
+ // Set the location to world.
+ m_nLocation = METEOR_LOCATION_WORLD;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CEnvMeteorShared::ConvertFromWorldToSkybox( void )
+{
+ // Scale the speed.
+ float flSkyboxScale = g_pMapData->Get3DSkyboxScale();
+ m_flSpeed /= flSkyboxScale;
+
+ float flDeltaTime = m_flWorldExitTime - m_flStartTime;
+ Vector vecVelocity( m_vecDirection.x * m_flSpeed, m_vecDirection.y * m_flSpeed, m_vecDirection.z * m_flSpeed );
+ VectorMA( m_vecStartPosition, flDeltaTime, vecVelocity, m_vecPos );
+
+ // Reset the start time.
+ m_flPosTime = m_flWorldExitTime;
+
+ // Set the location to skybox.
+ m_nLocation = METEOR_LOCATION_SKYBOX;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+bool CEnvMeteorShared::IsInSkybox( float flTime )
+{
+ // Check to see if we are always in the skybox!
+ if ( m_flWorldEnterTime == METEOR_INVALID_TIME )
+ return true;
+
+ return ( ( flTime < m_flWorldEnterTime ) || ( flTime > m_flWorldExitTime ) );
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+bool CEnvMeteorShared::IsPassive( float flTime )
+{
+ return ( flTime < m_flPassiveTime );
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+bool CEnvMeteorShared::WillTransition( void )
+{
+ return ( m_flWorldEnterTime == METEOR_INVALID_TIME );
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+float CEnvMeteorShared::GetDamageRadius( void )
+{
+ return m_flDamageRadius;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CEnvMeteorShared::CalcEnterAndExitTimes( const Vector &vecTriggerMins,
+ const Vector &vecTriggerMaxs )
+{
+#define METEOR_TRIGGER_EPSILON 0.001f
+
+ // Initialize the enter/exit fractions.
+ float flEnterFrac = 0.0f;
+ float flExitFrac = 1.0f;
+
+ // Create an arbitrarily large end position.
+ Vector vecEndPosition;
+ VectorMA( m_vecStartPosition, 32000.0f, m_vecDirection, vecEndPosition );
+
+ float flFrac, flDistStart, flDistEnd;
+ for( int iAxis = 0; iAxis < 3; iAxis++ )
+ {
+ // Negative Axis
+ flDistStart = -m_vecStartPosition[iAxis] + vecTriggerMins[iAxis];
+ flDistEnd = -vecEndPosition[iAxis] + vecTriggerMins[iAxis];
+
+ if ( ( flDistStart > 0.0f ) && ( flDistEnd < 0.0f ) )
+ {
+ flFrac = ( flDistStart - METEOR_TRIGGER_EPSILON ) / ( flDistStart - flDistEnd );
+ if ( flFrac > flEnterFrac ) { flEnterFrac = flFrac; }
+ }
+
+ if ( ( flDistStart < 0.0f ) && ( flDistEnd > 0.0f ) )
+ {
+ flFrac = ( flDistStart + METEOR_TRIGGER_EPSILON ) / ( flDistStart - flDistEnd );
+ if( flFrac < flExitFrac ) { flExitFrac = flFrac; }
+ }
+
+ if ( ( flDistStart > 0.0f ) && ( flDistEnd > 0.0f ) )
+ return;
+
+ // Positive Axis
+ flDistStart = m_vecStartPosition[iAxis] - vecTriggerMaxs[iAxis];
+ flDistEnd = vecEndPosition[iAxis] - vecTriggerMaxs[iAxis];
+
+ if ( ( flDistStart > 0.0f ) && ( flDistEnd < 0.0f ) )
+ {
+ flFrac = ( flDistStart - METEOR_TRIGGER_EPSILON ) / ( flDistStart - flDistEnd );
+ if ( flFrac > flEnterFrac ) { flEnterFrac = flFrac; }
+ }
+
+ if ( ( flDistStart < 0.0f ) && ( flDistEnd > 0.0f ) )
+ {
+ flFrac = ( flDistStart + METEOR_TRIGGER_EPSILON ) / ( flDistStart - flDistEnd );
+ if( flFrac < flExitFrac ) { flExitFrac = flFrac; }
+ }
+
+ if ( ( flDistStart > 0.0f ) && ( flDistEnd > 0.0f ) )
+ return;
+ }
+
+ // Check for intersection.
+ if ( flExitFrac >= flEnterFrac )
+ {
+ // Check to see if we start in the world or the skybox!
+ if ( flEnterFrac == 0.0f )
+ {
+ m_nLocation = METEOR_LOCATION_WORLD;
+ }
+ else
+ {
+ m_nLocation = METEOR_LOCATION_SKYBOX;
+ }
+
+ // Calculate the enter/exit times.
+ Vector vecEnterPoint, vecExitPoint, vecDeltaPosition;
+ VectorSubtract( vecEndPosition, m_vecStartPosition, vecDeltaPosition );
+ VectorScale( vecDeltaPosition, flEnterFrac, vecEnterPoint );
+ VectorScale( vecDeltaPosition, flExitFrac, vecExitPoint );
+
+ m_flWorldEnterTime = vecEnterPoint.Length() / m_flSpeed;
+ m_flWorldExitTime = vecExitPoint.Length() / m_flSpeed;
+ m_flWorldEnterTime += m_flStartTime;
+ m_flWorldExitTime += m_flStartTime;
+ }
+
+#undef METEOR_TRIGGER_EPSILON
+}
+
+//=============================================================================
+//
+// Meteor Spawner Functions.
+//
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+CEnvMeteorSpawnerShared::CEnvMeteorSpawnerShared()
+{
+ m_pFactory = NULL;
+ m_nMeteorCount = 0;
+
+ m_flStartTime = 0.0f;
+ m_nRandomSeed = 0;
+
+ m_iMeteorType = -1;
+ m_flMeteorDamageRadius = 0.0f;
+ m_bSkybox = true;
+
+ m_flMinSpawnTime = 0.0f;
+ m_flMaxSpawnTime = 0.0f;
+ m_nMinSpawnCount = 0;
+ m_nMaxSpawnCount = 0;
+ m_vecMinBounds.Init();
+ m_vecMaxBounds.Init();
+ m_flMinSpeed = 0.0f;
+ m_flMaxSpeed = 0.0f;
+
+ m_flNextSpawnTime = 0.0f;
+
+ m_vecTriggerMins.Init();
+ m_vecTriggerMaxs.Init();
+ m_vecTriggerCenter.Init();
+
+ // Debug!
+ m_nRandomCallCount = 0;
+
+ m_aTargets.Purge();
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CEnvMeteorSpawnerShared::Init( IMeteorFactory *pFactory, int nRandomSeed, float flTime,
+ const Vector &vecMinBounds, const Vector &vecMaxBounds,
+ const Vector &vecTriggerMins, const Vector &vecTriggerMaxs )
+{
+ // Factory.
+ m_pFactory = pFactory;
+
+ // Setup the random number stream.
+ m_nRandomSeed = nRandomSeed;
+ m_NumberStream.SetSeed( nRandomSeed );
+
+ // Start time.
+ m_flStartTime = flTime;
+
+ // Copy the spawner bounds.
+ m_vecMinBounds = vecMinBounds;
+ m_vecMaxBounds = vecMaxBounds;
+
+ // Copy the trigger bounds.
+ m_vecTriggerMins = vecTriggerMins;
+ m_vecTriggerMaxs = vecTriggerMaxs;
+
+ // Get the center of the trigger bounds.
+ m_vecTriggerCenter = ( m_vecTriggerMins + m_vecTriggerMaxs ) * 0.5f;
+
+ // Setup spawn time.
+ m_flNextSpawnTime = m_flStartTime + m_flMaxSpawnTime;
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+int CEnvMeteorSpawnerShared::GetRandomInt( int nMin, int nMax )
+{
+ m_nRandomCallCount++;
+ return m_NumberStream.RandomInt( nMin, nMax );
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+float CEnvMeteorSpawnerShared::GetRandomFloat( float flMin, float flMax )
+{
+ m_nRandomCallCount++;
+ return m_NumberStream.RandomFloat( flMin, flMax );
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+float CEnvMeteorSpawnerShared::MeteorThink( float flTime )
+{
+ // Check for spawn.
+ if ( flTime < m_flNextSpawnTime )
+ return m_flNextSpawnTime;
+
+ while ( m_flNextSpawnTime < flTime )
+ {
+ // Get a random number of meteors to spawn and spawn them.
+ int nMeteorCount = GetRandomInt( m_nMinSpawnCount, m_nMaxSpawnCount );
+ for ( int iMeteor = 0; iMeteor < nMeteorCount; iMeteor++ )
+ {
+ // Increment the number of meteors created (starting with 1).
+ m_nMeteorCount++;
+
+ // Get a random meteor position.
+ Vector meteorOrigin( GetRandomFloat( m_vecMinBounds.GetX(), m_vecMaxBounds.GetX() ) /* x */,
+ GetRandomFloat( m_vecMinBounds.GetY(), m_vecMaxBounds.GetY() ) /* y */,
+ GetRandomFloat( m_vecMinBounds.GetZ(), m_vecMaxBounds.GetZ() ) /* z */ );
+
+ // Calculate the direction of the meteor based on "targets."
+ Vector vecDirection( 0.0f, 0.0f, -1.0f );
+ if ( m_aTargets.Count() > 0 )
+ {
+ float flFreq = 1.0f / m_aTargets.Count();
+ float flFreqAccum = flFreq;
+
+ int iTarget;
+ for( iTarget = 0; iTarget < m_aTargets.Count(); ++iTarget )
+ {
+ float flRandom = GetRandomFloat( 0.0f, 1.0f );
+ if ( flRandom < flFreqAccum )
+ break;
+
+ flFreqAccum += flFreq;
+ }
+
+ // Should ever be here!
+ if ( iTarget == m_aTargets.Count() )
+ {
+ iTarget--;
+ }
+
+ // Just set it to the first target for now!!!
+ // NOTE: Will randomly generate from list of targets when more than 1 in
+ // the future.
+
+ // Move the meteor into the "world."
+ Vector vecPositionInWorld;
+ Vector vecSkyboxOrigin;
+ g_pMapData->Get3DSkyboxOrigin( vecSkyboxOrigin );
+ vecPositionInWorld = ( meteorOrigin - vecSkyboxOrigin );
+ vecPositionInWorld *= g_pMapData->Get3DSkyboxScale();
+
+ Vector vecTargetPos = m_aTargets[iTarget].m_vecPosition;
+ vecTargetPos.x += GetRandomFloat( -m_aTargets[iTarget].m_flRadius, m_aTargets[iTarget].m_flRadius );
+ vecTargetPos.y += GetRandomFloat( -m_aTargets[iTarget].m_flRadius, m_aTargets[iTarget].m_flRadius );
+ vecTargetPos.z += GetRandomFloat( -m_aTargets[iTarget].m_flRadius, m_aTargets[iTarget].m_flRadius );
+
+ vecDirection = vecTargetPos - vecPositionInWorld;
+ VectorNormalize( vecDirection );
+ }
+
+ // Pass in the randomized position, randomized speed, and start time.
+ m_pFactory->CreateMeteor( m_nMeteorCount, m_iMeteorType, meteorOrigin,
+ vecDirection /* direction */,
+ GetRandomFloat( m_flMinSpeed, m_flMaxSpeed ) /* speed */,
+ m_flNextSpawnTime, m_flMeteorDamageRadius,
+ m_vecTriggerMins, m_vecTriggerMaxs );
+ }
+
+ // Set next spawn time.
+ m_flNextSpawnTime += GetRandomFloat( m_flMinSpawnTime, m_flMaxSpawnTime );
+ }
+
+ // Return the next spawn time.
+ return ( m_flNextSpawnTime - gpGlobals->curtime );
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void CEnvMeteorSpawnerShared::AddToTargetList( const Vector &vecPosition, float flRadius )
+{
+ int iTarget = m_aTargets.AddToTail();
+ m_aTargets[iTarget].m_vecPosition = vecPosition;
+ m_aTargets[iTarget].m_flRadius = flRadius;
+}