diff options
Diffstat (limited to 'game/server/portal/func_portal_orientation.cpp')
| -rw-r--r-- | game/server/portal/func_portal_orientation.cpp | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/game/server/portal/func_portal_orientation.cpp b/game/server/portal/func_portal_orientation.cpp new file mode 100644 index 0000000..903d12b --- /dev/null +++ b/game/server/portal/func_portal_orientation.cpp @@ -0,0 +1,167 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//======================================================================================// + +#include "cbase.h" +#include "func_portal_orientation.h" +#include "prop_portal_shared.h" +#include "portal_shareddefs.h" +#include "portal_util_shared.h" +#include "portal_placement.h" +#include "collisionutils.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +CEntityClassList<CFuncPortalOrientation> g_FuncPortalOrientationVolumeList; +template <> CFuncPortalOrientation *CEntityClassList<CFuncPortalOrientation>::m_pClassList = NULL; + +CFuncPortalOrientation* GetPortalOrientationVolumeList() +{ + return g_FuncPortalOrientationVolumeList.m_pClassList; +} + +//----------------------------------------------------------------------------- +// Purpose: Test for func_orientation_volume ents which could effect the placement angles of a portal. +// Input : vecCurAngles - Default angles to place (may change) +// vecCurOrigin - origin of the portal on placement +// pPortal - The portal attempting to place +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool UTIL_TestForOrientationVolumes( QAngle& vecCurAngles, const Vector& vecCurOrigin, const CProp_Portal* pPortal ) +{ + if ( !pPortal ) + return false; + + // Walk list of orientation volumes, obb test each with candidate portal + CFuncPortalOrientation *pList = g_FuncPortalOrientationVolumeList.m_pClassList; + while ( pList ) + { + if ( !pList->IsActive() ) + { + pList = pList->m_pNext; + continue; + } + + if ( IsOBBIntersectingOBB( vecCurOrigin, vecCurAngles, CProp_Portal_Shared::vLocalMins, CProp_Portal_Shared::vLocalMaxs, + pList->GetAbsOrigin(), pList->GetCollideable()->GetCollisionAngles(), pList->GetCollideable()->OBBMins(), pList->GetCollideable()->OBBMaxs() ) ) + { + QAngle vecGoalAngles; + // Ent is marked to match angles of it's linked partner + if ( pList->m_bMatchLinkedAngles ) + { + // This feature requires a linked portal on a floor or ceiling. Bail without effecting + // the placement angles if we fail those requirements. + CProp_Portal* pLinked = pPortal->m_hLinkedPortal.Get(); + if ( !pLinked || !(AnglesAreEqual( vecCurAngles.x, -90.0f, 0.1f ) || AnglesAreEqual( vecCurAngles.x, 90.0f, 0.1f )) ) + return false; + + vecGoalAngles = pLinked->GetAbsAngles(); + vecCurAngles.y = 0.0f; + vecCurAngles.z = vecGoalAngles.z; + } + // Match the angles loaded in from the map + else + { + vecGoalAngles = pList->m_vecAnglesToFace; + vecCurAngles = vecGoalAngles; + } + + return true; + } + pList = pList->m_pNext; + } + + return false; +} + +LINK_ENTITY_TO_CLASS( func_portal_orientation, CFuncPortalOrientation ); + +BEGIN_DATADESC( CFuncPortalOrientation ) + + DEFINE_FIELD( m_iListIndex, FIELD_INTEGER ), + + //DEFINE_FIELD ( m_pNext, CFuncPortalOrientation ), + + DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ), + DEFINE_KEYFIELD ( m_bMatchLinkedAngles, FIELD_BOOLEAN, "MatchLinkedAngles" ), + DEFINE_KEYFIELD ( m_vecAnglesToFace, FIELD_VECTOR, "AnglesToFace" ), + + DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), + DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), + +END_DATADESC() + +CFuncPortalOrientation::CFuncPortalOrientation() +{ + g_FuncPortalOrientationVolumeList.Insert( this ); +} + +CFuncPortalOrientation::~CFuncPortalOrientation() +{ + g_FuncPortalOrientationVolumeList.Remove( this ); +} + +void CFuncPortalOrientation::Spawn() +{ + BaseClass::Spawn(); + + // Bind to our model, cause we need the extents for bounds checking + SetModel( STRING( GetModelName() ) ); + SetRenderMode( kRenderNone ); // Don't draw + SetSolid( SOLID_VPHYSICS ); // we may want slanted walls, so we'll use OBB + AddSolidFlags( FSOLID_NOT_SOLID ); +} + +//----------------------------------------------------------------------------- +// Purpose: Test for portals inside our volume when we switch on, and forcibly rotate them +//----------------------------------------------------------------------------- +void CFuncPortalOrientation::OnActivate( void ) +{ + if ( !GetCollideable() || m_bDisabled ) + return; + + int iPortalCount = CProp_Portal_Shared::AllPortals.Count(); + if( iPortalCount != 0 ) + { + CProp_Portal **pPortals = CProp_Portal_Shared::AllPortals.Base(); + for( int i = 0; i != iPortalCount; ++i ) + { + CProp_Portal *pTempPortal = pPortals[i]; + if( IsOBBIntersectingOBB( pTempPortal->GetAbsOrigin(), pTempPortal->GetAbsAngles(), CProp_Portal_Shared::vLocalMins, CProp_Portal_Shared::vLocalMaxs, + GetAbsOrigin(), GetCollideable()->GetCollisionAngles(), GetCollideable()->OBBMins(), GetCollideable()->OBBMaxs() ) ) + { + QAngle angNewAngles; + if ( m_bMatchLinkedAngles ) + { + CProp_Portal* pLinked = pTempPortal->m_hLinkedPortal.Get(); + if ( !pLinked ) + return; + + angNewAngles = pTempPortal->m_hLinkedPortal->GetAbsAngles(); + } + else + { + angNewAngles = m_vecAnglesToFace; + } + + pTempPortal->PlacePortal( pTempPortal->GetAbsOrigin(), angNewAngles, PORTAL_ANALOG_SUCCESS_NO_BUMP ); + } + } + } +} + +void CFuncPortalOrientation::InputEnable( inputdata_t &inputdata ) +{ + m_bDisabled = false; + + OnActivate(); +} + +void CFuncPortalOrientation::InputDisable( inputdata_t &inputdata ) +{ + m_bDisabled = true; +}
\ No newline at end of file |