|
|
//====== 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 ); // updates physics for all pushers that moved this tick
void UpdatePusherPhysicsEndOfTick(); void QueueChildUpdate( CBaseEntity *pChild ) { m_rgUpdatedChildren.AddToTail(pChild); }
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, bool bIgnoreTeammates = false );
// 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, bool bIgnoreTeammates ); void TraceBlockerEntity( CBaseEntity *pBlocker, const Vector& absStart, const Vector& absEnd, bool bIgnoreTeammates, trace_t *pOutTrace );
bool FindValidLocationUpwards( float *pOutLengthUp, CBaseEntity *pBlocker, float maxDist, float slop ); bool FindValidLocationAlongVector( Vector *pOutDelta, CBaseEntity *pBlocker, const Vector &vEndPoint, float slop );
protected:
CUtlVector<PhysicsPusherInfo_t> m_rgPusher; CUtlVector<PhysicsPushedInfo_t> m_rgMoved; int m_nBlocker; bool m_bIsUnblockableByPlayer; Vector m_rootPusherStartLocalOrigin; QAngle m_rootPusherStartLocalAngles; float m_rootPusherStartLocaltime; float m_flMoveTime;
CUtlVector<PhysicsPusherInfo_t> m_rgUpdatedPushers; CUtlVector<CBaseEntity *> m_rgUpdatedChildren; 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<CBaseEntity*>(pHandleEntity) ); CBaseEntity *pTestEntity = static_cast<CBaseEntity*>(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
|