You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
5.9 KiB
170 lines
5.9 KiB
//====== 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
|