From 39ed87570bdb2f86969d4be821c94b722dc71179 Mon Sep 17 00:00:00 2001 From: Joe Ludwig Date: Wed, 26 Jun 2013 15:22:04 -0700 Subject: First version of the SOurce SDK 2013 --- mp/src/game/shared/env_meteor_shared.cpp | 399 +++++++++++++++++++++++++++++++ 1 file changed, 399 insertions(+) create mode 100644 mp/src/game/shared/env_meteor_shared.cpp (limited to 'mp/src/game/shared/env_meteor_shared.cpp') 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; +} -- cgit v1.2.3