Seaside/SpyCustom/sdk/collisionproperty.h
2021-06-16 18:45:17 +03:00

380 lines
9.8 KiB
C++

#ifndef COLLISIONPROPERTY_H
#define COLLISIONPROPERTY_H
#ifdef _WIN32
#pragma once
#endif
#include "networkvar.h"
#include "ICollideable.h"
#include "vector.h"
#include "ispatialpartition.h"
class CBaseEntity;
class IHandleEntity;
class QAngle;
class Vector;
struct Ray_t;
class IPhysicsObject;
void UpdateDirtySpatialPartitionEntities();
enum SurroundingBoundsType_t
{
USE_OBB_COLLISION_BOUNDS = 0,
USE_BEST_COLLISION_BOUNDS,
USE_HITBOXES,
USE_SPECIFIED_BOUNDS,
USE_GAME_CODE,
USE_ROTATION_EXPANDED_BOUNDS,
USE_COLLISION_BOUNDS_NEVER_VPHYSICS,
SURROUNDING_TYPE_BIT_COUNT = 3
};
class CCollisionProperty : public ICollideable
{
DECLARE_CLASS_NOBASE(CCollisionProperty);
DECLARE_EMBEDDED_NETWORKVAR();
DECLARE_PREDICTABLE();
#ifdef GAME_DLL
DECLARE_DATADESC();
#endif
public:
CCollisionProperty();
~CCollisionProperty();
void Init(CBaseEntity* pEntity);
virtual IHandleEntity* GetEntityHandle();
virtual const Vector& OBBMinsPreScaled() const { return m_vecMinsPreScaled.Get(); }
virtual const Vector& OBBMaxsPreScaled() const { return m_vecMaxsPreScaled.Get(); }
virtual const Vector& OBBMins() const { return m_vecMins.Get(); }
virtual const Vector& OBBMaxs() const { return m_vecMaxs.Get(); }
virtual void WorldSpaceTriggerBounds(Vector* pVecWorldMins, Vector* pVecWorldMaxs) const;
virtual bool TestCollision(const Ray_t& ray, unsigned int fContentsMask, trace_t& tr);
virtual bool TestHitboxes(const Ray_t& ray, unsigned int fContentsMask, trace_t& tr);
virtual int GetCollisionModelIndex();
virtual const model_t* GetCollisionModel();
virtual const Vector& GetCollisionOrigin() const;
virtual const QAngle& GetCollisionAngles() const;
virtual const matrix3x4_t& CollisionToWorldTransform() const;
virtual SolidType_t GetSolid() const;
virtual int GetSolidFlags() const;
virtual IClientUnknown* GetIClientUnknown();
virtual int GetCollisionGroup() const;
virtual void WorldSpaceSurroundingBounds(Vector* pVecMins, Vector* pVecMaxs);
virtual bool ShouldTouchTrigger(int triggerSolidFlags) const;
virtual const matrix3x4_t* GetRootParentToWorldTransform() const;
public:
void CreatePartitionHandle();
void DestroyPartitionHandle();
unsigned short GetPartitionHandle() const;
void MarkPartitionHandleDirty();
void SetCollisionBounds(const Vector& mins, const Vector& maxs);
void RefreshScaledCollisionBounds(void);
void UseTriggerBounds(bool bEnable, float flBloat = 0.0f);
void SetSurroundingBoundsType(SurroundingBoundsType_t type, const Vector* pMins = NULL, const Vector* pMaxs = NULL);
void SetSolid(SolidType_t val);
const Vector& OBBSize() const;
float BoundingRadius() const;
float BoundingRadius2D() const;
const Vector& OBBCenter() const;
const Vector& WorldSpaceCenter() const;
void ClearSolidFlags(void);
void RemoveSolidFlags(int flags);
void AddSolidFlags(int flags);
bool IsSolidFlagSet(int flagMask) const;
void SetSolidFlags(int flags);
bool IsSolid() const;
void UpdatePartition();
bool IsBoundsDefinedInEntitySpace() const;
const Vector& CollisionToWorldSpace(const Vector& in, Vector* pResult) const;
const Vector& WorldToCollisionSpace(const Vector& in, Vector* pResult) const;
const Vector& WorldDirectionToCollisionSpace(const Vector& in, Vector* pResult) const;
void RandomPointInBounds(const Vector& vecNormalizedMins, const Vector& vecNormalizedMaxs, Vector* pPoint) const;
bool IsPointInBounds(const Vector& vecWorldPt) const;
void WorldSpaceAABB(Vector* pWorldMins, Vector* pWorldMaxs) const;
const Vector& CollisionSpaceMins(void) const;
const Vector& CollisionSpaceMaxs(void) const;
const Vector& NormalizedToCollisionSpace(const Vector& in, Vector* pResult) const;
const Vector& NormalizedToWorldSpace(const Vector& in, Vector* pResult) const;
const Vector& WorldToNormalizedSpace(const Vector& in, Vector* pResult) const;
const Vector& CollisionToNormalizedSpace(const Vector& in, Vector* pResult) const;
void CalcNearestPoint(const Vector& vecWorldPt, Vector* pVecNearestWorldPt) const;
float CalcDistanceFromPoint(const Vector& vecWorldPt) const;
bool DoesRotationInvalidateSurroundingBox() const;
bool DoesVPhysicsInvalidateSurroundingBox() const;
void MarkSurroundingBoundsDirty();
float ComputeSupportMap(const Vector& vecDirection) const;
private:
void CollisionAABBToWorldAABB(const Vector& entityMins, const Vector& entityMaxs, Vector* pWorldMins, Vector* pWorldMaxs) const;
void ComputeVPhysicsSurroundingBox(Vector* pVecWorldMins, Vector* pVecWorldMaxs);
bool ComputeHitboxSurroundingBox(Vector* pVecWorldMins, Vector* pVecWorldMaxs);
bool ComputeEntitySpaceHitboxSurroundingBox(Vector* pVecWorldMins, Vector* pVecWorldMaxs);
void ComputeCollisionSurroundingBox(bool bUseVPhysics, Vector* pVecWorldMins, Vector* pVecWorldMaxs);
void ComputeRotationExpandedBounds(Vector* pVecWorldMins, Vector* pVecWorldMaxs);
void ComputeSurroundingBox(Vector* pVecWorldMins, Vector* pVecWorldMaxs);
void CheckForUntouch();
void UpdateServerPartitionMask();
CBaseEntity* GetOuter();
const CBaseEntity* GetOuter() const;
private:
CBaseEntity* m_pOuter;
CNetworkVector(m_vecMinsPreScaled);
CNetworkVector(m_vecMaxsPreScaled);
CNetworkVector(m_vecMins);
CNetworkVector(m_vecMaxs);
float m_flRadius;
CNetworkVar(unsigned short, m_usSolidFlags);
SpatialPartitionHandle_t m_Partition;
CNetworkVar(unsigned char, m_nSurroundType);
CNetworkVar(unsigned char, m_nSolidType);
CNetworkVar(unsigned char, m_triggerBloat);
CNetworkVector(m_vecSpecifiedSurroundingMinsPreScaled);
CNetworkVector(m_vecSpecifiedSurroundingMaxsPreScaled);
CNetworkVector(m_vecSpecifiedSurroundingMins);
CNetworkVector(m_vecSpecifiedSurroundingMaxs);
#if 0
short m_surroundingMins[3];
short m_surroundingMaxs[3];
#else
Vector m_vecSurroundingMins;
Vector m_vecSurroundingMaxs;
#endif
friend class CBaseEntity;
};
#ifdef CLIENT_DLL
EXTERN_RECV_TABLE(DT_CollisionProperty);
#else
EXTERN_SEND_TABLE(DT_CollisionProperty);
#endif
inline CBaseEntity* CCollisionProperty::GetOuter()
{
return m_pOuter;
}
inline const CBaseEntity* CCollisionProperty::GetOuter() const
{
return m_pOuter;
}
inline unsigned short CCollisionProperty::GetPartitionHandle() const
{
return m_Partition;
}
inline const Vector& CCollisionProperty::OBBSize() const
{
Vector& temp = AllocTempVector();
VectorSubtract(m_vecMaxs, m_vecMins, temp);
return temp;
}
inline float CCollisionProperty::BoundingRadius() const
{
return m_flRadius;
}
inline bool CCollisionProperty::IsBoundsDefinedInEntitySpace() const
{
return ((m_usSolidFlags & FSOLID_FORCE_WORLD_ALIGNED) == 0) &&
(m_nSolidType != SOLID_BBOX) && (m_nSolidType != SOLID_NONE);
}
inline void CCollisionProperty::ClearSolidFlags(void)
{
SetSolidFlags(0);
}
inline void CCollisionProperty::RemoveSolidFlags(int flags)
{
SetSolidFlags(m_usSolidFlags & ~flags);
}
inline void CCollisionProperty::AddSolidFlags(int flags)
{
SetSolidFlags(m_usSolidFlags | flags);
}
inline int CCollisionProperty::GetSolidFlags(void) const
{
return m_usSolidFlags;
}
inline bool CCollisionProperty::IsSolidFlagSet(int flagMask) const
{
return (m_usSolidFlags & flagMask) != 0;
}
inline bool CCollisionProperty::IsSolid() const
{
return ::IsSolid((SolidType_t)(unsigned char)m_nSolidType, m_usSolidFlags);
}
inline const Vector& CCollisionProperty::OBBCenter() const
{
Vector& vecResult = AllocTempVector();
VectorLerp(m_vecMins, m_vecMaxs, 0.5f, vecResult);
return vecResult;
}
inline const Vector& CCollisionProperty::WorldSpaceCenter() const
{
Vector& vecResult = AllocTempVector();
CollisionToWorldSpace(OBBCenter(), &vecResult);
return vecResult;
}
inline const Vector& CCollisionProperty::CollisionToWorldSpace(const Vector& in, Vector* pResult) const
{
if (!IsBoundsDefinedInEntitySpace() || (GetCollisionAngles() == vec3_angle))
{
VectorAdd(in, GetCollisionOrigin(), *pResult);
}
else
{
VectorTransform(in, CollisionToWorldTransform(), *pResult);
}
return *pResult;
}
inline const Vector& CCollisionProperty::WorldToCollisionSpace(const Vector& in, Vector* pResult) const
{
if (!IsBoundsDefinedInEntitySpace() || (GetCollisionAngles() == vec3_angle))
{
VectorSubtract(in, GetCollisionOrigin(), *pResult);
}
else
{
VectorITransform(in, CollisionToWorldTransform(), *pResult);
}
return *pResult;
}
inline const Vector& CCollisionProperty::WorldDirectionToCollisionSpace(const Vector& in, Vector* pResult) const
{
if (!IsBoundsDefinedInEntitySpace() || (GetCollisionAngles() == vec3_angle))
{
*pResult = in;
}
else
{
VectorIRotate(in, CollisionToWorldTransform(), *pResult);
}
return *pResult;
}
inline void CCollisionProperty::WorldSpaceAABB(Vector* pWorldMins, Vector* pWorldMaxs) const
{
CollisionAABBToWorldAABB(m_vecMins, m_vecMaxs, pWorldMins, pWorldMaxs);
}
inline const Vector& CCollisionProperty::CollisionSpaceMins(void) const
{
return m_vecMins;
}
inline const Vector& CCollisionProperty::CollisionSpaceMaxs(void) const
{
return m_vecMaxs;
}
inline bool CCollisionProperty::DoesRotationInvalidateSurroundingBox() const
{
if (IsSolidFlagSet(FSOLID_ROOT_PARENT_ALIGNED))
return true;
switch (m_nSurroundType)
{
case USE_COLLISION_BOUNDS_NEVER_VPHYSICS:
case USE_OBB_COLLISION_BOUNDS:
case USE_BEST_COLLISION_BOUNDS:
return IsBoundsDefinedInEntitySpace();
case USE_HITBOXES:
case USE_GAME_CODE:
return true;
case USE_ROTATION_EXPANDED_BOUNDS:
case USE_SPECIFIED_BOUNDS:
return false;
default:
Assert(0);
return true;
}
}
#endif