diff options
| author | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:31:46 -0800 |
|---|---|---|
| committer | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:46:31 -0800 |
| commit | f56bb35301836e56582a575a75864392a0177875 (patch) | |
| tree | de61ddd39de3e7df52759711950b4c288592f0dc /mp/src/game/server/trigger_portal.cpp | |
| parent | Mark some more files as text. (diff) | |
| download | source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip | |
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/game/server/trigger_portal.cpp')
| -rw-r--r-- | mp/src/game/server/trigger_portal.cpp | 684 |
1 files changed, 342 insertions, 342 deletions
diff --git a/mp/src/game/server/trigger_portal.cpp b/mp/src/game/server/trigger_portal.cpp index 5e7eb911..17508047 100644 --- a/mp/src/game/server/trigger_portal.cpp +++ b/mp/src/game/server/trigger_portal.cpp @@ -1,343 +1,343 @@ -//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: Entity which teleports touched entities and reorients their physics
-//
-//=============================================================================//
-
-#include "cbase.h"
-#include "baseentity.h"
-#include "triggers.h"
-#include "modelentities.h"
-#include "saverestore_utlvector.h"
-#include "player_pickup.h"
-#include "vphysics/friction.h"
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-#define TRIGGER_DISABLED_THINK "PortalDisabledThink"
-
-ConVar portal_debug( "portal_debug", "0", FCVAR_CHEAT, "Turn on debugging for portal connections." );
-
-//////////////////////////////////////////////////////////////////////////
-// CTriggerPortal
-// Moves touched entity to a target location, changing the model's orientation
-// to match the exit target. It differs from CTriggerTeleport in that it
-// reorients physics and has inputs to enable/disable its function.
-//////////////////////////////////////////////////////////////////////////
-class CTriggerPortal : public CBaseTrigger
-{
-public:
- DECLARE_DATADESC();
- DECLARE_CLASS( CTriggerPortal, CBaseTrigger );
- DECLARE_SERVERCLASS();
-
- virtual void Spawn( void );
- virtual void Activate();
-
- void Touch( CBaseEntity *pOther );
- void EndTouch(CBaseEntity *pOther);
- void DisableForIncomingEntity( CBaseEntity *pEntity );
- bool IsTouchingPortal( CBaseEntity *pEntity );
-
- void DisabledThink( void );
-
- // TEMP: Since brushes have no directionality, give this wall a forward face specified in hammer
- QAngle m_qFaceAngles;
-
-private:
- string_t m_strRemotePortal;
- CNetworkHandle( CTriggerPortal, m_hRemotePortal );
- CUtlVector<EHANDLE> m_hDisabledForEntities;
-
- // Input for setting remote portal entity (for teleporting to it)
- void SetRemotePortal ( const char* strRemotePortalName );
- void InputSetRemotePortal ( inputdata_t &inputdata );
-
-};
-
-LINK_ENTITY_TO_CLASS( trigger_portal, CTriggerPortal );
-
-BEGIN_DATADESC( CTriggerPortal )
- DEFINE_KEYFIELD( m_strRemotePortal, FIELD_STRING, "RemotePortal" ),
-
- DEFINE_FIELD( m_hRemotePortal, FIELD_EHANDLE ),
- DEFINE_UTLVECTOR( m_hDisabledForEntities, FIELD_EHANDLE ),
-
- // TEMP: Only keep this field while portals are still brushes
- DEFINE_FIELD( m_qFaceAngles, FIELD_VECTOR ),
-
- DEFINE_THINKFUNC( DisabledThink ),
-
- DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
- DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
- DEFINE_INPUTFUNC( FIELD_STRING, "SetRemotePortal", InputSetRemotePortal ),
-END_DATADESC()
-
-IMPLEMENT_SERVERCLASS_ST( CTriggerPortal, DT_TriggerPortal )
- SendPropEHandle(SENDINFO(m_hRemotePortal)),
-END_SEND_TABLE()
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CTriggerPortal::Spawn( void )
-{
- BaseClass::Spawn();
-
- InitTrigger();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : -
-//-----------------------------------------------------------------------------
-void CTriggerPortal::Activate()
-{
- BaseClass::Activate();
-
- m_qFaceAngles = this->GetAbsAngles();
-
- // keep the remote portal's pointer at activate time to avoid redundant FindEntity calls
- if ( m_strRemotePortal != NULL_STRING )
- {
- SetRemotePortal( STRING(m_strRemotePortal) );
- m_strRemotePortal = NULL_STRING;
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : &inputdata -
-//-----------------------------------------------------------------------------
-void CTriggerPortal::InputSetRemotePortal(inputdata_t &inputdata )
-{
- SetRemotePortal( inputdata.value.String() );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : strRemotePortalName -
-//-----------------------------------------------------------------------------
-void CTriggerPortal::SetRemotePortal(const char *strRemotePortalName )
-{
- m_hRemotePortal = dynamic_cast<CTriggerPortal*> (gEntList.FindEntityByName( NULL, strRemotePortalName, NULL, NULL, NULL ));
- if ( m_hRemotePortal == NULL )
- {
- Warning ( "trigger_portal: Cannot find remote portal entity named %s\n", strRemotePortalName );
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : *pOther -
-//-----------------------------------------------------------------------------
-void CTriggerPortal::EndTouch(CBaseEntity *pOther)
-{
- BaseClass::EndTouch(pOther);
-
- if ( portal_debug.GetBool() )
- {
- Msg("%s ENDTOUCH: for %s\n", GetDebugName(), pOther->GetDebugName() );
- }
-
- EHANDLE hHandle;
- hHandle = pOther;
- m_hDisabledForEntities.FindAndRemove( hHandle );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Upon touching a non-filtered entity, CTriggerPortal teleports them to it's
-// remote portal location.
-// Input : *pOther -
-//-----------------------------------------------------------------------------
-void CTriggerPortal::Touch( CBaseEntity *pOther )
-{
- // If we are enabled, and allowed to react to the touched entity
- if ( PassesTriggerFilters(pOther) )
- {
- // If we somehow lost our pointer to the remote portal, get a new one
- if ( m_hRemotePortal == NULL )
- {
- Disable();
- return;
- }
-
- bool bDebug = portal_debug.GetBool();
- if ( bDebug )
- {
- Msg("%s TOUCH: for %s\n", GetDebugName(), pOther->GetDebugName() );
- }
-
- // Don't touch entities that came through us and haven't left us yet.
- EHANDLE hHandle;
- hHandle = pOther;
- if ( m_hDisabledForEntities.Find(hHandle) != m_hDisabledForEntities.InvalidIndex() )
- {
- Msg(" IGNORED\n", GetDebugName(), pOther->GetDebugName() );
- return;
- }
-
- Pickup_ForcePlayerToDropThisObject( pOther );
-
- // de-ground this entity
- pOther->SetGroundEntity( NULL );
-
- // Build a this --> remote transformation
- VMatrix matMyModelToWorld, matMyInverse;
- matMyModelToWorld = this->EntityToWorldTransform();
- MatrixInverseGeneral ( matMyModelToWorld, matMyInverse );
-
- // Teleport our object
- VMatrix matRemotePortalTransform = m_hRemotePortal->EntityToWorldTransform();
- Vector ptNewOrigin, vLook, vRight, vUp, vNewLook;
- pOther->GetVectors( &vLook, &vRight, &vUp );
-
- // Move origin
- ptNewOrigin = matMyInverse * pOther->GetAbsOrigin();
- ptNewOrigin = matRemotePortalTransform * Vector( ptNewOrigin.x, -ptNewOrigin.y, ptNewOrigin.z );
-
- // Re-aim camera
- vNewLook = matMyInverse.ApplyRotation( vLook );
- vNewLook = matRemotePortalTransform.ApplyRotation( Vector( -vNewLook.x, -vNewLook.y, vNewLook.z ) );
-
- // Reorient the physics
- Vector vVelocity, vOldVelocity;
- pOther->GetVelocity( &vOldVelocity );
- vVelocity = matMyInverse.ApplyRotation( vOldVelocity );
- vVelocity = matRemotePortalTransform.ApplyRotation( Vector( -vVelocity.x, -vVelocity.y, vVelocity.z ) );
-
- QAngle qNewAngles;
- VectorAngles( vNewLook, qNewAngles );
-
- if ( pOther->IsPlayer() )
- {
- ((CBasePlayer*)pOther)->SnapEyeAngles(qNewAngles);
- }
-
- Vector vecOldPos = pOther->WorldSpaceCenter();
- if ( bDebug )
- {
- NDebugOverlay::Box( pOther->GetAbsOrigin(), pOther->WorldAlignMins(), pOther->WorldAlignMaxs(), 255,0,0, 8, 20 );
- NDebugOverlay::Axis( pOther->GetAbsOrigin(), pOther->GetAbsAngles(), 10.0f, true, 50 );
- }
-
- // place player at the new destination
- CTriggerPortal *pPortal = m_hRemotePortal.Get();
- pPortal->DisableForIncomingEntity( pOther );
- pOther->Teleport( &ptNewOrigin, &qNewAngles, &vVelocity );
-
- if ( bDebug )
- {
- NDebugOverlay::Box( pOther->GetAbsOrigin(), pOther->WorldAlignMins(), pOther->WorldAlignMaxs(), 0,255,0, 8, 20 );
- NDebugOverlay::Line( vecOldPos, pOther->WorldSpaceCenter(), 0,255,0, true, 20 );
- NDebugOverlay::Axis( pOther->GetAbsOrigin(), pOther->GetAbsAngles(), 10.0f, true, 50 );
-
- Msg("%s TELEPORTED: %s\n", GetDebugName(), pOther->GetDebugName() );
- }
-
- // test collision on the new teleport location
- Vector vMin, vMax, vCenter;
- pOther->CollisionProp()->WorldSpaceAABB( &vMin, &vMax );
- vCenter = (vMin + vMax) * 0.5f;
- vMin -= vCenter;
- vMax -= vCenter;
-
- Vector vStart, vEnd;
- vStart = ptNewOrigin;
- vEnd = ptNewOrigin;
-
- Ray_t ray;
- ray.Init( vStart, vEnd, vMin, vMax );
- trace_t tr;
- pPortal->TestCollision( ray, pOther->PhysicsSolidMaskForEntity(), tr );
-
- // Teleportation caused us to hit something, deal with it.
- if ( tr.DidHit() )
- {
-
- }
-
-
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CTriggerPortal::DisableForIncomingEntity( CBaseEntity *pEntity )
-{
- EHANDLE hHandle;
- hHandle = pEntity;
- Assert( m_hDisabledForEntities.Find(hHandle) == m_hDisabledForEntities.InvalidIndex() );
- m_hDisabledForEntities.AddToTail( hHandle );
-
- // Start thinking, and remove the other as soon as it's not touching me.
- // Needs to be done in addition to EndTouch, because entities may move fast
- // enough through the portal to come out not touching the other portal.
- SetContextThink( DisabledThink, gpGlobals->curtime + 0.1, TRIGGER_DISABLED_THINK );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CTriggerPortal::DisabledThink( void )
-{
- // If we've got no disabled entities left, we're done
- if ( !m_hDisabledForEntities.Count() )
- {
- SetContextThink( NULL, gpGlobals->curtime, TRIGGER_DISABLED_THINK );
- return;
- }
-
- for ( int i = m_hDisabledForEntities.Count()-1; i >= 0; i-- )
- {
- CBaseEntity *pEntity = m_hDisabledForEntities[i];
- if ( !pEntity || !IsTouchingPortal(pEntity) )
- {
- m_hDisabledForEntities.Remove(i);
- }
- }
-
- SetContextThink( DisabledThink, gpGlobals->curtime + 0.1, TRIGGER_DISABLED_THINK );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-bool CTriggerPortal::IsTouchingPortal( CBaseEntity *pEntity )
-{
- // First, check the touchlinks. This will find non-vphysics entities touching us
- touchlink_t *root = ( touchlink_t * )GetDataObject( TOUCHLINK );
- if ( root )
- {
- for ( touchlink_t *link = root->nextLink; link != root; link = link->nextLink )
- {
- CBaseEntity *pTouch = link->entityTouched;
- if ( pTouch == pEntity )
- return true;
- }
- }
-
- // Then check the friction snapshot. This will find vphysics objects touching us.
- IPhysicsObject *pPhysics = VPhysicsGetObject();
- if ( !pPhysics )
- return false;
-
- IPhysicsFrictionSnapshot *pSnapshot = pPhysics->CreateFrictionSnapshot();
- bool bFound = false;
- while ( pSnapshot->IsValid() )
- {
- IPhysicsObject *pOther = pSnapshot->GetObject( 1 );
- if ( ((CBaseEntity *)pOther->GetGameData()) == pEntity )
- {
- bFound = true;
- break;
- }
-
- pSnapshot->NextFrictionData();
- }
- pPhysics->DestroyFrictionSnapshot( pSnapshot );
-
- return bFound;
+//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Entity which teleports touched entities and reorients their physics +// +//=============================================================================// + +#include "cbase.h" +#include "baseentity.h" +#include "triggers.h" +#include "modelentities.h" +#include "saverestore_utlvector.h" +#include "player_pickup.h" +#include "vphysics/friction.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#define TRIGGER_DISABLED_THINK "PortalDisabledThink" + +ConVar portal_debug( "portal_debug", "0", FCVAR_CHEAT, "Turn on debugging for portal connections." ); + +////////////////////////////////////////////////////////////////////////// +// CTriggerPortal +// Moves touched entity to a target location, changing the model's orientation +// to match the exit target. It differs from CTriggerTeleport in that it +// reorients physics and has inputs to enable/disable its function. +////////////////////////////////////////////////////////////////////////// +class CTriggerPortal : public CBaseTrigger +{ +public: + DECLARE_DATADESC(); + DECLARE_CLASS( CTriggerPortal, CBaseTrigger ); + DECLARE_SERVERCLASS(); + + virtual void Spawn( void ); + virtual void Activate(); + + void Touch( CBaseEntity *pOther ); + void EndTouch(CBaseEntity *pOther); + void DisableForIncomingEntity( CBaseEntity *pEntity ); + bool IsTouchingPortal( CBaseEntity *pEntity ); + + void DisabledThink( void ); + + // TEMP: Since brushes have no directionality, give this wall a forward face specified in hammer + QAngle m_qFaceAngles; + +private: + string_t m_strRemotePortal; + CNetworkHandle( CTriggerPortal, m_hRemotePortal ); + CUtlVector<EHANDLE> m_hDisabledForEntities; + + // Input for setting remote portal entity (for teleporting to it) + void SetRemotePortal ( const char* strRemotePortalName ); + void InputSetRemotePortal ( inputdata_t &inputdata ); + +}; + +LINK_ENTITY_TO_CLASS( trigger_portal, CTriggerPortal ); + +BEGIN_DATADESC( CTriggerPortal ) + DEFINE_KEYFIELD( m_strRemotePortal, FIELD_STRING, "RemotePortal" ), + + DEFINE_FIELD( m_hRemotePortal, FIELD_EHANDLE ), + DEFINE_UTLVECTOR( m_hDisabledForEntities, FIELD_EHANDLE ), + + // TEMP: Only keep this field while portals are still brushes + DEFINE_FIELD( m_qFaceAngles, FIELD_VECTOR ), + + DEFINE_THINKFUNC( DisabledThink ), + + DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), + DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), + DEFINE_INPUTFUNC( FIELD_STRING, "SetRemotePortal", InputSetRemotePortal ), +END_DATADESC() + +IMPLEMENT_SERVERCLASS_ST( CTriggerPortal, DT_TriggerPortal ) + SendPropEHandle(SENDINFO(m_hRemotePortal)), +END_SEND_TABLE() + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTriggerPortal::Spawn( void ) +{ + BaseClass::Spawn(); + + InitTrigger(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : - +//----------------------------------------------------------------------------- +void CTriggerPortal::Activate() +{ + BaseClass::Activate(); + + m_qFaceAngles = this->GetAbsAngles(); + + // keep the remote portal's pointer at activate time to avoid redundant FindEntity calls + if ( m_strRemotePortal != NULL_STRING ) + { + SetRemotePortal( STRING(m_strRemotePortal) ); + m_strRemotePortal = NULL_STRING; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : &inputdata - +//----------------------------------------------------------------------------- +void CTriggerPortal::InputSetRemotePortal(inputdata_t &inputdata ) +{ + SetRemotePortal( inputdata.value.String() ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : strRemotePortalName - +//----------------------------------------------------------------------------- +void CTriggerPortal::SetRemotePortal(const char *strRemotePortalName ) +{ + m_hRemotePortal = dynamic_cast<CTriggerPortal*> (gEntList.FindEntityByName( NULL, strRemotePortalName, NULL, NULL, NULL )); + if ( m_hRemotePortal == NULL ) + { + Warning ( "trigger_portal: Cannot find remote portal entity named %s\n", strRemotePortalName ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pOther - +//----------------------------------------------------------------------------- +void CTriggerPortal::EndTouch(CBaseEntity *pOther) +{ + BaseClass::EndTouch(pOther); + + if ( portal_debug.GetBool() ) + { + Msg("%s ENDTOUCH: for %s\n", GetDebugName(), pOther->GetDebugName() ); + } + + EHANDLE hHandle; + hHandle = pOther; + m_hDisabledForEntities.FindAndRemove( hHandle ); +} + +//----------------------------------------------------------------------------- +// Purpose: Upon touching a non-filtered entity, CTriggerPortal teleports them to it's +// remote portal location. +// Input : *pOther - +//----------------------------------------------------------------------------- +void CTriggerPortal::Touch( CBaseEntity *pOther ) +{ + // If we are enabled, and allowed to react to the touched entity + if ( PassesTriggerFilters(pOther) ) + { + // If we somehow lost our pointer to the remote portal, get a new one + if ( m_hRemotePortal == NULL ) + { + Disable(); + return; + } + + bool bDebug = portal_debug.GetBool(); + if ( bDebug ) + { + Msg("%s TOUCH: for %s\n", GetDebugName(), pOther->GetDebugName() ); + } + + // Don't touch entities that came through us and haven't left us yet. + EHANDLE hHandle; + hHandle = pOther; + if ( m_hDisabledForEntities.Find(hHandle) != m_hDisabledForEntities.InvalidIndex() ) + { + Msg(" IGNORED\n", GetDebugName(), pOther->GetDebugName() ); + return; + } + + Pickup_ForcePlayerToDropThisObject( pOther ); + + // de-ground this entity + pOther->SetGroundEntity( NULL ); + + // Build a this --> remote transformation + VMatrix matMyModelToWorld, matMyInverse; + matMyModelToWorld = this->EntityToWorldTransform(); + MatrixInverseGeneral ( matMyModelToWorld, matMyInverse ); + + // Teleport our object + VMatrix matRemotePortalTransform = m_hRemotePortal->EntityToWorldTransform(); + Vector ptNewOrigin, vLook, vRight, vUp, vNewLook; + pOther->GetVectors( &vLook, &vRight, &vUp ); + + // Move origin + ptNewOrigin = matMyInverse * pOther->GetAbsOrigin(); + ptNewOrigin = matRemotePortalTransform * Vector( ptNewOrigin.x, -ptNewOrigin.y, ptNewOrigin.z ); + + // Re-aim camera + vNewLook = matMyInverse.ApplyRotation( vLook ); + vNewLook = matRemotePortalTransform.ApplyRotation( Vector( -vNewLook.x, -vNewLook.y, vNewLook.z ) ); + + // Reorient the physics + Vector vVelocity, vOldVelocity; + pOther->GetVelocity( &vOldVelocity ); + vVelocity = matMyInverse.ApplyRotation( vOldVelocity ); + vVelocity = matRemotePortalTransform.ApplyRotation( Vector( -vVelocity.x, -vVelocity.y, vVelocity.z ) ); + + QAngle qNewAngles; + VectorAngles( vNewLook, qNewAngles ); + + if ( pOther->IsPlayer() ) + { + ((CBasePlayer*)pOther)->SnapEyeAngles(qNewAngles); + } + + Vector vecOldPos = pOther->WorldSpaceCenter(); + if ( bDebug ) + { + NDebugOverlay::Box( pOther->GetAbsOrigin(), pOther->WorldAlignMins(), pOther->WorldAlignMaxs(), 255,0,0, 8, 20 ); + NDebugOverlay::Axis( pOther->GetAbsOrigin(), pOther->GetAbsAngles(), 10.0f, true, 50 ); + } + + // place player at the new destination + CTriggerPortal *pPortal = m_hRemotePortal.Get(); + pPortal->DisableForIncomingEntity( pOther ); + pOther->Teleport( &ptNewOrigin, &qNewAngles, &vVelocity ); + + if ( bDebug ) + { + NDebugOverlay::Box( pOther->GetAbsOrigin(), pOther->WorldAlignMins(), pOther->WorldAlignMaxs(), 0,255,0, 8, 20 ); + NDebugOverlay::Line( vecOldPos, pOther->WorldSpaceCenter(), 0,255,0, true, 20 ); + NDebugOverlay::Axis( pOther->GetAbsOrigin(), pOther->GetAbsAngles(), 10.0f, true, 50 ); + + Msg("%s TELEPORTED: %s\n", GetDebugName(), pOther->GetDebugName() ); + } + + // test collision on the new teleport location + Vector vMin, vMax, vCenter; + pOther->CollisionProp()->WorldSpaceAABB( &vMin, &vMax ); + vCenter = (vMin + vMax) * 0.5f; + vMin -= vCenter; + vMax -= vCenter; + + Vector vStart, vEnd; + vStart = ptNewOrigin; + vEnd = ptNewOrigin; + + Ray_t ray; + ray.Init( vStart, vEnd, vMin, vMax ); + trace_t tr; + pPortal->TestCollision( ray, pOther->PhysicsSolidMaskForEntity(), tr ); + + // Teleportation caused us to hit something, deal with it. + if ( tr.DidHit() ) + { + + } + + + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTriggerPortal::DisableForIncomingEntity( CBaseEntity *pEntity ) +{ + EHANDLE hHandle; + hHandle = pEntity; + Assert( m_hDisabledForEntities.Find(hHandle) == m_hDisabledForEntities.InvalidIndex() ); + m_hDisabledForEntities.AddToTail( hHandle ); + + // Start thinking, and remove the other as soon as it's not touching me. + // Needs to be done in addition to EndTouch, because entities may move fast + // enough through the portal to come out not touching the other portal. + SetContextThink( DisabledThink, gpGlobals->curtime + 0.1, TRIGGER_DISABLED_THINK ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTriggerPortal::DisabledThink( void ) +{ + // If we've got no disabled entities left, we're done + if ( !m_hDisabledForEntities.Count() ) + { + SetContextThink( NULL, gpGlobals->curtime, TRIGGER_DISABLED_THINK ); + return; + } + + for ( int i = m_hDisabledForEntities.Count()-1; i >= 0; i-- ) + { + CBaseEntity *pEntity = m_hDisabledForEntities[i]; + if ( !pEntity || !IsTouchingPortal(pEntity) ) + { + m_hDisabledForEntities.Remove(i); + } + } + + SetContextThink( DisabledThink, gpGlobals->curtime + 0.1, TRIGGER_DISABLED_THINK ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CTriggerPortal::IsTouchingPortal( CBaseEntity *pEntity ) +{ + // First, check the touchlinks. This will find non-vphysics entities touching us + touchlink_t *root = ( touchlink_t * )GetDataObject( TOUCHLINK ); + if ( root ) + { + for ( touchlink_t *link = root->nextLink; link != root; link = link->nextLink ) + { + CBaseEntity *pTouch = link->entityTouched; + if ( pTouch == pEntity ) + return true; + } + } + + // Then check the friction snapshot. This will find vphysics objects touching us. + IPhysicsObject *pPhysics = VPhysicsGetObject(); + if ( !pPhysics ) + return false; + + IPhysicsFrictionSnapshot *pSnapshot = pPhysics->CreateFrictionSnapshot(); + bool bFound = false; + while ( pSnapshot->IsValid() ) + { + IPhysicsObject *pOther = pSnapshot->GetObject( 1 ); + if ( ((CBaseEntity *)pOther->GetGameData()) == pEntity ) + { + bFound = true; + break; + } + + pSnapshot->NextFrictionData(); + } + pPhysics->DestroyFrictionSnapshot( pSnapshot ); + + return bFound; }
\ No newline at end of file |