summaryrefslogtreecommitdiff
path: root/game/shared/hl2/env_headcrabcanister_shared.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'game/shared/hl2/env_headcrabcanister_shared.cpp')
-rw-r--r--game/shared/hl2/env_headcrabcanister_shared.cpp393
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
+}
+