161 lines
5.6 KiB
C++
161 lines
5.6 KiB
C++
//========= Copyright 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);
|
|
|
|
// Speculatively checks to see if all entities in this list can be pushed
|
|
virtual bool SpeculativelyCheckRotPush(
|
|
const RotatingPushMove_t &rotPushMove, CBaseEntity *pRoot);
|
|
|
|
// 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<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;
|
|
|
|
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
|