diff options
Diffstat (limited to 'game/server/physics_collisionevent.h')
| -rw-r--r-- | game/server/physics_collisionevent.h | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/game/server/physics_collisionevent.h b/game/server/physics_collisionevent.h new file mode 100644 index 0000000..67f91d3 --- /dev/null +++ b/game/server/physics_collisionevent.h @@ -0,0 +1,176 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Pulling CCollisionEvent's definition out of physics.cpp so it can be abstracted upon (for the portal mod) +// +// +// $Workfile: $ +// $Date: $ +// $NoKeywords: $ +//=============================================================================// + +#ifndef PHYSICS_COLLISIONEVENT_H +#define PHYSICS_COLLISIONEVENT_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "physics.h" +#include "tier1/callqueue.h" + +extern CCallQueue g_PostSimulationQueue; + +struct damageevent_t +{ + CBaseEntity *pEntity; + IPhysicsObject *pInflictorPhysics; + CTakeDamageInfo info; + bool bRestoreVelocity; +}; + +struct inflictorstate_t +{ + Vector savedVelocity; + AngularImpulse savedAngularVelocity; + IPhysicsObject *pInflictorPhysics; + float otherMassMax; + short nextIndex; + short restored; +}; + +enum +{ + COLLSTATE_ENABLED = 0, + COLLSTATE_TRYDISABLE = 1, + COLLSTATE_TRYNPCSOLVER = 2, + COLLSTATE_TRYENTITYSOLVER = 3, + COLLSTATE_DISABLED = 4 +}; + +struct penetrateevent_t +{ + EHANDLE hEntity0; + EHANDLE hEntity1; + float startTime; + float timeStamp; + int collisionState; +}; + +class CCollisionEvent : public IPhysicsCollisionEvent, public IPhysicsCollisionSolver, public IPhysicsObjectEvent +{ +public: + CCollisionEvent(); + friction_t *FindFriction( CBaseEntity *pObject ); + void ShutdownFriction( friction_t &friction ); + void FrameUpdate(); + void LevelShutdown( void ); + + // IPhysicsCollisionEvent + void PreCollision( vcollisionevent_t *pEvent ); + void PostCollision( vcollisionevent_t *pEvent ); + void Friction( IPhysicsObject *pObject, float energy, int surfaceProps, int surfacePropsHit, IPhysicsCollisionData *pData ); + void StartTouch( IPhysicsObject *pObject1, IPhysicsObject *pObject2, IPhysicsCollisionData *pTouchData ); + void EndTouch( IPhysicsObject *pObject1, IPhysicsObject *pObject2, IPhysicsCollisionData *pTouchData ); + void FluidStartTouch( IPhysicsObject *pObject, IPhysicsFluidController *pFluid ); + void FluidEndTouch( IPhysicsObject *pObject, IPhysicsFluidController *pFluid ); + void PostSimulationFrame(); + void ObjectEnterTrigger( IPhysicsObject *pTrigger, IPhysicsObject *pObject ); + void ObjectLeaveTrigger( IPhysicsObject *pTrigger, IPhysicsObject *pObject ); + + bool GetTriggerEvent( triggerevent_t *pEvent, CBaseEntity *pTriggerEntity ); + void BufferTouchEvents( bool enable ) { m_bBufferTouchEvents = enable; } + virtual void AddDamageEvent( CBaseEntity *pEntity, const CTakeDamageInfo &info, IPhysicsObject *pInflictorPhysics, bool bRestoreVelocity, const Vector &savedVel, const AngularImpulse &savedAngVel ); + void AddImpulseEvent( IPhysicsObject *pPhysicsObject, const Vector &vecCenterForce, const AngularImpulse &vecCenterTorque ); + void AddSetVelocityEvent( IPhysicsObject *pPhysicsObject, const Vector &vecVelocity ); + void AddRemoveObject(IServerNetworkable *pRemove); + void FlushQueuedOperations(); + + // IPhysicsCollisionSolver + int ShouldCollide( IPhysicsObject *pObj0, IPhysicsObject *pObj1, void *pGameData0, void *pGameData1 ); + int ShouldSolvePenetration( IPhysicsObject *pObj0, IPhysicsObject *pObj1, void *pGameData0, void *pGameData1, float dt ); + bool ShouldFreezeObject( IPhysicsObject *pObject ); + static const char *ModuleName() { return CBaseEntity::IsServer() ? "SERVER" : "CLIENT"; } + int AdditionalCollisionChecksThisTick( int currentChecksDone ) + { + //CallbackContext check(this); + if ( currentChecksDone < 1200 ) + { + DevMsg(1,"%s: VPhysics Collision detection getting expensive, check for too many convex pieces!\n", ModuleName()); + return 1200 - currentChecksDone; + } + DevMsg(1,"%s: VPhysics exceeded collision check limit (%d)!!!\nInterpenetration may result!\n", ModuleName(), currentChecksDone ); + return 0; + } + bool ShouldFreezeContacts( IPhysicsObject **pObjectList, int objectCount ); + + // IPhysicsObjectEvent + // these can be used to optimize out queries on sleeping objects + // Called when an object is woken after sleeping + virtual void ObjectWake( IPhysicsObject *pObject ); + // called when an object goes to sleep (no longer simulating) + virtual void ObjectSleep( IPhysicsObject *pObject ); + + + // locals + bool GetInflictorVelocity( IPhysicsObject *pInflictor, Vector &velocity, AngularImpulse &angVelocity ); + + void GetListOfPenetratingEntities( CBaseEntity *pSearch, CUtlVector<CBaseEntity *> &list ); + bool IsInCallback() { return m_inCallback > 0 ? true : false; } + +private: +#if _DEBUG + int ShouldCollide_2( IPhysicsObject *pObj0, IPhysicsObject *pObj1, void *pGameData0, void *pGameData1 ); +#endif + + void UpdateFrictionSounds(); + void UpdateTouchEvents(); + void UpdateDamageEvents(); + void UpdatePenetrateEvents( void ); + void UpdateFluidEvents(); + void UpdateRemoveObjects(); + void AddTouchEvent( CBaseEntity *pEntity0, CBaseEntity *pEntity1, int touchType, const Vector &point, const Vector &normal ); + penetrateevent_t &FindOrAddPenetrateEvent( CBaseEntity *pEntity0, CBaseEntity *pEntity1 ); + float DeltaTimeSinceLastFluid( CBaseEntity *pEntity ); + + void RestoreDamageInflictorState( IPhysicsObject *pInflictor ); + void RestoreDamageInflictorState( int inflictorStateIndex, float velocityBlend ); + int AddDamageInflictor( IPhysicsObject *pInflictorPhysics, float otherMass, const Vector &savedVel, const AngularImpulse &savedAngVel, bool addList ); + int FindDamageInflictor( IPhysicsObject *pInflictorPhysics ); + + // make the call into the entity system + void DispatchStartTouch( CBaseEntity *pEntity0, CBaseEntity *pEntity1, const Vector &point, const Vector &normal ); + void DispatchEndTouch( CBaseEntity *pEntity0, CBaseEntity *pEntity1 ); + + class CallbackContext + { + public: + CallbackContext(CCollisionEvent *pOuter) + { + m_pOuter = pOuter; + m_pOuter->m_inCallback++; + } + ~CallbackContext() + { + m_pOuter->m_inCallback--; + } + private: + CCollisionEvent *m_pOuter; + }; + friend class CallbackContext; + + friction_t m_current[4]; + gamevcollisionevent_t m_gameEvent; + CUtlVector<triggerevent_t> m_triggerEvents; + triggerevent_t m_currentTriggerEvent; + CUtlVector<touchevent_t> m_touchEvents; + CUtlVector<damageevent_t> m_damageEvents; + CUtlVector<inflictorstate_t> m_damageInflictors; + CUtlVector<penetrateevent_t> m_penetrateEvents; + CUtlVector<fluidevent_t> m_fluidEvents; + CUtlVector<IServerNetworkable *> m_removeObjects; + int m_inCallback; + int m_lastTickFrictionError; // counter to control printing of the dev warning for large contact systems + bool m_bBufferTouchEvents; +}; + +#endif //#ifndef PHYSICS_COLLISIONEVENT_H |