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/shared/hl2/env_headcrabcanister_shared.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/shared/hl2/env_headcrabcanister_shared.cpp')
| -rw-r--r-- | game/shared/hl2/env_headcrabcanister_shared.cpp | 393 |
1 files changed, 393 insertions, 0 deletions
diff --git a/game/shared/hl2/env_headcrabcanister_shared.cpp b/game/shared/hl2/env_headcrabcanister_shared.cpp new file mode 100644 index 0000000..036e39c --- /dev/null +++ b/game/shared/hl2/env_headcrabcanister_shared.cpp @@ -0,0 +1,393 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// +#include "cbase.h" +#include "env_headcrabcanister_shared.h" +#include "mapdata_shared.h" +#include "sharedInterface.h" +#include "mathlib/vmatrix.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#define ROTATION_SPEED 90.0f + + +BEGIN_SIMPLE_DATADESC( CEnvHeadcrabCanisterShared ) + DEFINE_FIELD( m_vecStartPosition, FIELD_POSITION_VECTOR ), + DEFINE_FIELD( m_vecEnterWorldPosition, FIELD_POSITION_VECTOR ), + DEFINE_FIELD( m_vecDirection, FIELD_VECTOR ), + DEFINE_FIELD( m_vecStartAngles, FIELD_VECTOR ), + DEFINE_KEYFIELD( m_flLaunchHeight, FIELD_FLOAT, "StartingHeight" ), + DEFINE_KEYFIELD( m_flFlightSpeed, FIELD_FLOAT, "FlightSpeed" ), + DEFINE_KEYFIELD( m_flFlightTime, FIELD_FLOAT, "FlightTime" ), + DEFINE_FIELD( m_flLaunchTime, FIELD_TIME ), + DEFINE_FIELD( m_flWorldEnterTime, FIELD_FLOAT ), + DEFINE_FIELD( m_flInitialZSpeed, FIELD_FLOAT ), + DEFINE_FIELD( m_flZAcceleration, FIELD_FLOAT ), + DEFINE_FIELD( m_flHorizSpeed, FIELD_FLOAT ), + DEFINE_FIELD( m_bLaunchedFromWithinWorld, FIELD_BOOLEAN ), + DEFINE_FIELD( m_vecSkyboxOrigin, FIELD_VECTOR ), + DEFINE_FIELD( m_vecParabolaDirection, FIELD_VECTOR ), + DEFINE_FIELD( m_flSkyboxScale, FIELD_FLOAT ), + DEFINE_FIELD( m_bInSkybox, FIELD_BOOLEAN ), +END_DATADESC() + + +BEGIN_NETWORK_TABLE_NOBASE( CEnvHeadcrabCanisterShared, DT_EnvHeadcrabCanisterShared ) + +#if !defined( CLIENT_DLL ) + SendPropFloat ( SENDINFO( m_flFlightSpeed ), 0, SPROP_NOSCALE ), + SendPropTime ( SENDINFO( m_flLaunchTime ) ), + SendPropVector ( SENDINFO( m_vecParabolaDirection ), 0, SPROP_NOSCALE ), + + SendPropFloat ( SENDINFO( m_flFlightTime ), 0, SPROP_NOSCALE ), + SendPropFloat ( SENDINFO( m_flWorldEnterTime ), 0, SPROP_NOSCALE ), + + SendPropFloat ( SENDINFO( m_flInitialZSpeed ), 0, SPROP_NOSCALE ), + SendPropFloat ( SENDINFO( m_flZAcceleration ), 0, SPROP_NOSCALE ), + SendPropFloat ( SENDINFO( m_flHorizSpeed ), 0, SPROP_NOSCALE ), + SendPropBool ( SENDINFO( m_bLaunchedFromWithinWorld ) ), + + SendPropVector ( SENDINFO( m_vecStartPosition ), 0, SPROP_NOSCALE ), + SendPropVector ( SENDINFO( m_vecEnterWorldPosition ), 0, SPROP_NOSCALE ), + SendPropVector ( SENDINFO( m_vecDirection ), 0, SPROP_NOSCALE ), + SendPropVector ( SENDINFO( m_vecStartAngles ), 0, SPROP_NOSCALE ), + + SendPropVector ( SENDINFO( m_vecSkyboxOrigin ), 0, SPROP_NOSCALE ), + SendPropFloat ( SENDINFO( m_flSkyboxScale ), 0, SPROP_NOSCALE ), + SendPropBool ( SENDINFO( m_bInSkybox ) ), +#else + RecvPropFloat ( RECVINFO( m_flFlightSpeed ) ), + RecvPropTime ( RECVINFO( m_flLaunchTime ) ), + RecvPropVector ( RECVINFO( m_vecParabolaDirection ) ), + + RecvPropFloat ( RECVINFO( m_flFlightTime ) ), + RecvPropFloat ( RECVINFO( m_flWorldEnterTime ) ), + + RecvPropFloat ( RECVINFO( m_flInitialZSpeed ) ), + RecvPropFloat ( RECVINFO( m_flZAcceleration ) ), + RecvPropFloat ( RECVINFO( m_flHorizSpeed ) ), + RecvPropBool ( RECVINFO( m_bLaunchedFromWithinWorld ) ), + + RecvPropVector ( RECVINFO( m_vecStartPosition ) ), + RecvPropVector ( RECVINFO( m_vecEnterWorldPosition ) ), + RecvPropVector ( RECVINFO( m_vecDirection ) ), + RecvPropVector ( RECVINFO( m_vecStartAngles ) ), + + RecvPropVector ( RECVINFO( m_vecSkyboxOrigin ) ), + RecvPropFloat ( RECVINFO( m_flSkyboxScale ) ), + RecvPropBool ( RECVINFO( m_bInSkybox ) ), +#endif + +END_NETWORK_TABLE() + + + +//============================================================================= +// +// HeadcrabCanister Functions. +// + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- +CEnvHeadcrabCanisterShared::CEnvHeadcrabCanisterShared() +{ + m_vecStartPosition.Init(); + m_vecDirection.Init(); + m_flFlightSpeed = 0.0f; + + // This tells the client DLL to not draw trails, etc. + m_flLaunchTime = -1.0f; + + m_flWorldEnterTime = 0.0f; + m_flFlightTime = 0.0f; + m_bInSkybox = false; +} + + +//----------------------------------------------------------------------------- +// Creates a headcrab canister in the world +//----------------------------------------------------------------------------- +void CEnvHeadcrabCanisterShared::InitInWorld( float flLaunchTime, + const Vector &vecStartPosition, const QAngle &vecStartAngles, + const Vector &vecDirection, const Vector &vecImpactPosition, bool bLaunchedFromWithinWorld ) +{ + Vector vecActualStartPosition = vecStartPosition; + if ( !bLaunchedFromWithinWorld ) + { + // Move the start position inward if it's too close + Vector vecDelta; + VectorSubtract( vecStartPosition, vecImpactPosition, vecDelta ); + VectorNormalize( vecDelta ); + + VectorMA( vecImpactPosition, m_flFlightTime * m_flFlightSpeed, vecDelta, vecActualStartPosition ); + } + + // Setup initial parametric state. + m_flLaunchTime = flLaunchTime; + m_vecStartPosition = vecActualStartPosition; + m_vecEnterWorldPosition = vecActualStartPosition; + m_vecDirection = vecDirection; + m_vecStartAngles = vecStartAngles; + m_flWorldEnterTime = 0.0f; + m_bInSkybox = false; + m_bLaunchedFromWithinWorld = bLaunchedFromWithinWorld; + + if ( m_bLaunchedFromWithinWorld ) + { + m_flSkyboxScale = 1; + m_vecSkyboxOrigin = vec3_origin; + + float flLength = m_vecDirection.Get().AsVector2D().Length(); + VectorSubtract(vecImpactPosition, vecStartPosition, m_vecParabolaDirection.GetForModify()); + m_vecParabolaDirection.GetForModify().z = 0; + float flTotalDistance = VectorNormalize( m_vecParabolaDirection.GetForModify() ); + m_vecDirection.GetForModify().x = flLength * m_vecParabolaDirection.Get().x; + m_vecDirection.GetForModify().y = flLength * m_vecParabolaDirection.Get().y; + + m_flHorizSpeed = flTotalDistance / m_flFlightTime; + m_flWorldEnterTime = 0; + + float flFinalZSpeed = m_vecDirection.Get().z * m_flHorizSpeed; + m_flFlightSpeed = sqrt( m_flHorizSpeed * m_flHorizSpeed + flFinalZSpeed * flFinalZSpeed ); + m_flInitialZSpeed = (2.0f * ( vecImpactPosition.z - vecStartPosition.z ) - flFinalZSpeed * m_flFlightTime) / m_flFlightTime; + m_flZAcceleration = (flFinalZSpeed - m_flInitialZSpeed) / m_flFlightTime; + } +} + + +//----------------------------------------------------------------------------- +// Creates a headcrab canister in the skybox +//----------------------------------------------------------------------------- +void CEnvHeadcrabCanisterShared::InitInSkybox( float flLaunchTime, + const Vector &vecStartPosition, const QAngle &vecStartAngles, const Vector &vecDirection, + const Vector &vecImpactPosition, const Vector &vecSkyboxOrigin, float flSkyboxScale ) +{ + // Compute a horizontal speed (constant) + m_vecParabolaDirection.Init( vecDirection.x, vecDirection.y, 0.0f ); + float flLength = VectorNormalize( m_vecParabolaDirection.GetForModify() ); + m_flHorizSpeed = flLength * m_flFlightSpeed; + + // compute total distance to travel + float flTotalDistance = m_flFlightTime * m_flHorizSpeed; + flTotalDistance -= vecStartPosition.AsVector2D().DistTo( vecImpactPosition.AsVector2D() ); + if ( flTotalDistance <= 0.0f ) + { + InitInWorld( flLaunchTime, vecStartPosition, vecStartAngles, vecDirection, vecImpactPosition ); + return; + } + + // Setup initial parametric state. + m_flLaunchTime = flLaunchTime; + m_flWorldEnterTime = flTotalDistance / m_flHorizSpeed; + m_vecSkyboxOrigin = vecSkyboxOrigin; + m_flSkyboxScale = flSkyboxScale; + + m_vecEnterWorldPosition = vecStartPosition; + m_vecDirection = vecDirection; + m_vecStartAngles = vecStartAngles; + m_bInSkybox = true; + m_bLaunchedFromWithinWorld = false; + + // Compute parabolic course + // Assume the x velocity remains constant. + // Z moves ballistically, as if under gravity + // zf + lh = zo + // vf = vo + a*t + // zf = zo + vo*t + 0.5 * a * t*t + // a*t = vf - vo + // zf = zo + vo*t + 0.5f * (vf - vo) * t + // zf - zo = 0.5f *vo*t + 0.5f * vf * t + // -lh - 0.5f * vf * t = 0.5f * vo * t + // vo = -2.0f * lh / t - vf + // a = (vf - vo) / t + m_flHorizSpeed /= flSkyboxScale; + + VectorMA( vecSkyboxOrigin, 1.0f / m_flSkyboxScale, vecStartPosition, m_vecStartPosition.GetForModify() ); + VectorMA( m_vecStartPosition.Get(), -m_flHorizSpeed * m_flWorldEnterTime, m_vecParabolaDirection, m_vecStartPosition.GetForModify() ); + + float flLaunchHeight = m_flLaunchHeight / flSkyboxScale; + float flFinalZSpeed = m_vecDirection.Get().z * m_flFlightSpeed / flSkyboxScale; + m_vecStartPosition.GetForModify().z += flLaunchHeight; + m_flZAcceleration = 2.0f * ( flLaunchHeight + flFinalZSpeed * m_flWorldEnterTime ) / ( m_flWorldEnterTime * m_flWorldEnterTime ); + m_flInitialZSpeed = flFinalZSpeed - m_flZAcceleration * m_flWorldEnterTime; +} + + +//----------------------------------------------------------------------------- +// Convert from skybox to world +//----------------------------------------------------------------------------- +void CEnvHeadcrabCanisterShared::ConvertFromSkyboxToWorld() +{ + Assert( m_bInSkybox ); + m_bInSkybox = false; +} + + +//----------------------------------------------------------------------------- +// Returns the time at which it enters the world +//----------------------------------------------------------------------------- +float CEnvHeadcrabCanisterShared::GetEnterWorldTime() const +{ + return m_flWorldEnterTime; +} + + +//----------------------------------------------------------------------------- +// Did we impact? +//----------------------------------------------------------------------------- +bool CEnvHeadcrabCanisterShared::DidImpact( float flTime ) const +{ + return (flTime - m_flLaunchTime) >= m_flFlightTime; +} + + +//----------------------------------------------------------------------------- +// Computes the position of the canister +//----------------------------------------------------------------------------- +void CEnvHeadcrabCanisterShared::GetPositionAtTime( float flTime, Vector &vecPosition, QAngle &vecAngles ) +{ + float flDeltaTime = flTime - m_flLaunchTime; + if ( flDeltaTime > m_flFlightTime ) + { + flDeltaTime = m_flFlightTime; + } + + VMatrix initToWorld; + if ( m_bLaunchedFromWithinWorld || m_bInSkybox ) + { + VectorMA( m_vecStartPosition, flDeltaTime * m_flHorizSpeed, m_vecParabolaDirection, vecPosition ); + vecPosition.z += m_flInitialZSpeed * flDeltaTime + 0.5f * m_flZAcceleration * flDeltaTime * flDeltaTime; + + Vector vecLeft; + CrossProduct( m_vecParabolaDirection, Vector( 0, 0, 1 ), vecLeft ); + + Vector vecForward; + VectorMultiply( m_vecParabolaDirection, -1.0f, vecForward ); + vecForward.z = -(m_flInitialZSpeed + m_flZAcceleration * flDeltaTime) / m_flHorizSpeed; // This is -dz/dx. + VectorNormalize( vecForward ); + + Vector vecUp; + CrossProduct( vecForward, vecLeft, vecUp ); + + initToWorld.SetBasisVectors( vecForward, vecLeft, vecUp ); + } + else + { + flDeltaTime -= m_flWorldEnterTime; + Vector vecVelocity; + VectorMultiply( m_vecDirection, m_flFlightSpeed, vecVelocity ); + VectorMA( m_vecEnterWorldPosition, flDeltaTime, vecVelocity, vecPosition ); + + MatrixFromAngles( m_vecStartAngles.Get(), initToWorld ); + } + + VMatrix rotation; + MatrixBuildRotationAboutAxis( rotation, Vector( 1, 0, 0 ), flDeltaTime * ROTATION_SPEED ); + + VMatrix newAngles; + MatrixMultiply( initToWorld, rotation, newAngles ); + MatrixToAngles( newAngles, vecAngles ); +} + + +//----------------------------------------------------------------------------- +// Are we in the skybox? +//----------------------------------------------------------------------------- +bool CEnvHeadcrabCanisterShared::IsInSkybox( ) +{ + // Check to see if we are always in the world! + return m_bInSkybox; +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void CEnvHeadcrabCanisterShared::CalcEnterTime( const Vector &vecTriggerMins, + const Vector &vecTriggerMaxs ) +{ + /* +#define HEADCRABCANISTER_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 - HEADCRABCANISTER_TRIGGER_EPSILON ) / ( flDistStart - flDistEnd ); + if ( flFrac > flEnterFrac ) { flEnterFrac = flFrac; } + } + + if ( ( flDistStart < 0.0f ) && ( flDistEnd > 0.0f ) ) + { + flFrac = ( flDistStart + HEADCRABCANISTER_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 - HEADCRABCANISTER_TRIGGER_EPSILON ) / ( flDistStart - flDistEnd ); + if ( flFrac > flEnterFrac ) { flEnterFrac = flFrac; } + } + + if ( ( flDistStart < 0.0f ) && ( flDistEnd > 0.0f ) ) + { + flFrac = ( flDistStart + HEADCRABCANISTER_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 = HEADCRABCANISTER_LOCATION_WORLD; + } + else + { + m_nLocation = HEADCRABCANISTER_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_flFlightSpeed; + m_flWorldEnterTime += m_flLaunchTime; + } + */ + +#undef HEADCRABCANISTER_TRIGGER_EPSILON +} + |