//====== Copyright © 1996-2008, Valve Corporation, All rights reserved. ======= // // Purpose: // //============================================================================= #ifndef PUSHENTITY_H #define PUSHENTITY_H #ifdef _WIN32 #pragma once #endif #include "movetype_push.h" //----------------------------------------------------------------------------- // Purpose: Keeps track of original positions of any entities that are being possibly pushed // and handles restoring positions for those objects if the push is aborted //----------------------------------------------------------------------------- class CPhysicsPushedEntities { public: DECLARE_CLASS_NOBASE( CPhysicsPushedEntities ); CPhysicsPushedEntities( void ); // Purpose: Tries to rotate an entity hierarchy, returns the blocker if any CBaseEntity *PerformRotatePush( CBaseEntity *pRoot, float movetime ); // Purpose: Tries to linearly push an entity hierarchy, returns the blocker if any CBaseEntity *PerformLinearPush( CBaseEntity *pRoot, float movetime ); int CountMovedEntities() { return m_rgMoved.Count(); } void StoreMovedEntities( physicspushlist_t &list ); void BeginPush( CBaseEntity *pRootEntity ); protected: // describes the per-frame incremental motion of a rotating MOVETYPE_PUSH struct RotatingPushMove_t { Vector origin; matrix3x4_t startLocalToWorld; matrix3x4_t endLocalToWorld; QAngle amove; // delta orientation }; // Pushers + their original positions also (for touching triggers) struct PhysicsPusherInfo_t { CBaseEntity *m_pEntity; Vector m_vecStartAbsOrigin; }; // Pushed entities + various state related to them being pushed struct PhysicsPushedInfo_t { CBaseEntity *m_pEntity; Vector m_vecStartAbsOrigin; trace_t m_Trace; bool m_bBlocked; bool m_bPusherIsGround; }; // Adds the specified entity to the list void AddEntity( CBaseEntity *ent ); // If a move fails, restores all entities to their original positions void RestoreEntities( ); // Compute the direction to move the rotation blocker void ComputeRotationalPushDirection( CBaseEntity *pBlocker, const RotatingPushMove_t &rotPushMove, Vector *pMove, CBaseEntity *pRoot ); // Speculatively checks to see if all entities in this list can be pushed bool SpeculativelyCheckPush( PhysicsPushedInfo_t &info, const Vector &vecAbsPush, bool bRotationalPush, CBaseEntity *pRoot ); // Speculatively checks to see if all entities in this list can be pushed virtual bool SpeculativelyCheckRotPush( const RotatingPushMove_t &rotPushMove, CBaseEntity *pRoot = NULL ); // Speculatively checks to see if all entities in this list can be pushed virtual bool SpeculativelyCheckLinearPush( const Vector &vecAbsPush ); // Registers a blockage CBaseEntity *RegisterBlockage(); // Some fixup for objects pushed by rotating objects virtual void FinishRotPushedEntity( CBaseEntity *pPushedEntity, const RotatingPushMove_t &rotPushMove ); // Commits the speculative movement void FinishPush( bool bIsRotPush = false, const RotatingPushMove_t *pRotPushMove = NULL ); // Generates a list of all entities potentially blocking all pushers void GenerateBlockingEntityList(); void GenerateBlockingEntityListAddBox( const Vector &vecMoved ); // Purpose: Gets a list of all entities hierarchically attached to the root void SetupAllInHierarchy( CBaseEntity *pParent ); // Unlink + relink the pusher list so we can actually do the push void UnlinkPusherList( int *pPusherHandles ); void RelinkPusherList( int *pPusherHandles ); // Causes all entities in the list to touch triggers from their prev position void FinishPushers(); // Purpose: Rotates the root entity, fills in the pushmove structure void RotateRootEntity( CBaseEntity *pRoot, float movetime, RotatingPushMove_t &rotation ); // Purpose: Linearly moves the root entity void LinearlyMoveRootEntity( CBaseEntity *pRoot, float movetime, Vector *pAbsPushVector ); bool IsPushedPositionValid( CBaseEntity *pBlocker ); protected: CUtlVector m_rgPusher; CUtlVector m_rgMoved; int m_nBlocker; bool m_bIsUnblockableByPlayer; Vector m_rootPusherStartLocalOrigin; QAngle m_rootPusherStartLocalAngles; float m_rootPusherStartLocaltime; float m_flMoveTime; friend class CPushBlockerEnum; }; class CTraceFilterPushMove : public CTraceFilterSimple { DECLARE_CLASS( CTraceFilterPushMove, CTraceFilterSimple ); public: CTraceFilterPushMove( CBaseEntity *pEntity, int nCollisionGroup ) : CTraceFilterSimple( pEntity, nCollisionGroup ) { m_pRootParent = pEntity->GetRootMoveParent(); } bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) { Assert( dynamic_cast(pHandleEntity) ); CBaseEntity *pTestEntity = static_cast(pHandleEntity); if ( UTIL_EntityHasMatchingRootParent( m_pRootParent, pTestEntity ) ) return false; if ( pTestEntity->GetMoveType() == MOVETYPE_VPHYSICS && pTestEntity->VPhysicsGetObject() && pTestEntity->VPhysicsGetObject()->IsMoveable() ) return false; return BaseClass::ShouldHitEntity( pHandleEntity, contentsMask ); } private: CBaseEntity *m_pRootParent; }; extern CPhysicsPushedEntities *g_pPushedEntities; #endif // PUSHENTITY_H