1
0
mirror of https://github.com/alliedmodders/hl2sdk.git synced 2024-12-23 01:59:43 +08:00

Add CGameTrace, CTraceFilter, Ray_t & trace ray related enums/defines (#254)

This commit is contained in:
vanz696 2024-06-07 14:29:04 +03:00 committed by GitHub
parent 49a2b0b4ef
commit 6056e92838
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 755 additions and 462 deletions

View File

@ -42,6 +42,7 @@ void Sys_Error (char *error, ...);
#endif
const QAngle vec3_angle(0,0,0);
const Quaternion quat_identity(0,0,0,1);
const Vector vec3_invalid( FLT_MAX, FLT_MAX, FLT_MAX );
const int nanmask = 255<<23;

View File

@ -14,6 +14,8 @@
#pragma once
#endif
#include "const.h"
// contents flags are seperate bits
// a given brush can contribute multiple content bits
// multiple brushes can be in a single leaf
@ -21,136 +23,80 @@
// these definitions also need to be in q_shared.h!
// lower bits are stronger, and will eat weaker brushes completely
#define CONTENTS_EMPTY 0 // No contents
#define CONTENTS_EMPTY 0ull // No contents
#define CONTENTS_SOLID 0x1 // an eye is never valid in a solid
#define CONTENTS_WINDOW 0x2 // translucent, but not watery (glass)
#define CONTENTS_AUX 0x4
#define CONTENTS_GRATE 0x8 // alpha-tested "grate" textures. Bullets/sight pass through, but solids don't
#define CONTENTS_SLIME 0x10
#define CONTENTS_WATER 0x20
#define CONTENTS_BLOCKLOS 0x40 // block AI line of sight
#define CONTENTS_OPAQUE 0x80 // things that cannot be seen through (may be non-solid though)
#define LAST_VISIBLE_CONTENTS CONTENTS_OPAQUE
#define CONTENTS_SOLID ( 1ull << LAYER_INDEX_CONTENTS_SOLID )
#define CONTENTS_HITBOX ( 1ull << LAYER_INDEX_CONTENTS_HITBOX )
#define CONTENTS_TRIGGER ( 1ull << LAYER_INDEX_CONTENTS_TRIGGER )
#define CONTENTS_SKY ( 1ull << LAYER_INDEX_CONTENTS_SKY )
#define ALL_VISIBLE_CONTENTS (LAST_VISIBLE_CONTENTS | (LAST_VISIBLE_CONTENTS-1))
#define CONTENTS_PLAYER_CLIP ( 1ull << LAYER_INDEX_CONTENTS_PLAYER_CLIP )
#define CONTENTS_NPC_CLIP ( 1ull << LAYER_INDEX_CONTENTS_NPC_CLIP )
#define CONTENTS_BLOCK_LOS ( 1ull << LAYER_INDEX_CONTENTS_BLOCK_LOS )
#define CONTENTS_BLOCK_LIGHT ( 1ull << LAYER_INDEX_CONTENTS_BLOCK_LIGHT )
#define CONTENTS_LADDER ( 1ull << LAYER_INDEX_CONTENTS_LADDER )
#define CONTENTS_PICKUP ( 1ull << LAYER_INDEX_CONTENTS_PICKUP )
#define CONTENTS_BLOCK_SOUND ( 1ull << LAYER_INDEX_CONTENTS_BLOCK_SOUND )
#define CONTENTS_NODRAW ( 1ull << LAYER_INDEX_CONTENTS_NODRAW )
#define CONTENTS_WINDOW ( 1ull << LAYER_INDEX_CONTENTS_WINDOW )
#define CONTENTS_PASS_BULLETS ( 1ull << LAYER_INDEX_CONTENTS_PASS_BULLETS )
#define CONTENTS_WORLD_GEOMETRY ( 1ull << LAYER_INDEX_CONTENTS_WORLD_GEOMETRY )
#define CONTENTS_WATER ( 1ull << LAYER_INDEX_CONTENTS_WATER )
#define CONTENTS_SLIME ( 1ull << LAYER_INDEX_CONTENTS_SLIME )
#define CONTENTS_TOUCH_ALL ( 1ull << LAYER_INDEX_CONTENTS_TOUCH_ALL )
#define CONTENTS_PLAYER ( 1ull << LAYER_INDEX_CONTENTS_PLAYER )
#define CONTENTS_NPC ( 1ull << LAYER_INDEX_CONTENTS_NPC )
#define CONTENTS_DEBRIS ( 1ull << LAYER_INDEX_CONTENTS_DEBRIS )
#define CONTENTS_PHYSICS_PROP ( 1ull << LAYER_INDEX_CONTENTS_PHYSICS_PROP )
#define CONTENTS_NAV_IGNORE ( 1ull << LAYER_INDEX_CONTENTS_NAV_IGNORE )
#define CONTENTS_NAV_LOCAL_IGNORE ( 1ull << LAYER_INDEX_CONTENTS_NAV_LOCAL_IGNORE )
#define CONTENTS_POST_PROCESSING_VOLUME ( 1ull << LAYER_INDEX_CONTENTS_POST_PROCESSING_VOLUME )
#define CONTENTS_UNUSED_LAYER3 ( 1ull << LAYER_INDEX_CONTENTS_UNUSED_LAYER3 )
#define CONTENTS_CARRIED_OBJECT ( 1ull << LAYER_INDEX_CONTENTS_CARRIED_OBJECT )
#define CONTENTS_PUSHAWAY ( 1ull << LAYER_INDEX_CONTENTS_PUSHAWAY )
#define CONTENTS_SERVER_ENTITY_ON_CLIENT ( 1ull << LAYER_INDEX_CONTENTS_SERVER_ENTITY_ON_CLIENT )
#define CONTENTS_CARRIED_WEAPON ( 1ull << LAYER_INDEX_CONTENTS_CARRIED_WEAPON )
#define CONTENTS_STATIC_LEVEL ( 1ull << LAYER_INDEX_CONTENTS_STATIC_LEVEL )
#define CONTENTS_TESTFOGVOLUME 0x100
#define CONTENTS_UNUSED 0x200
// unused
// NOTE: If it's visible, grab from the top + update LAST_VISIBLE_CONTENTS
// if not visible, then grab from the bottom.
// CONTENTS_OPAQUE + SURF_NODRAW count as CONTENTS_OPAQUE (shadow-casting toolsblocklight textures)
#define CONTENTS_BLOCKLIGHT 0x400
#define CONTENTS_TEAM1 0x800 // per team contents used to differentiate collisions
#define CONTENTS_TEAM2 0x1000 // between players and objects on different teams
// ignore CONTENTS_OPAQUE on surfaces that have SURF_NODRAW
#define CONTENTS_IGNORE_NODRAW_OPAQUE 0x2000
// hits entities which are MOVETYPE_PUSH (doors, plats, etc.)
#define CONTENTS_MOVEABLE 0x4000
// remaining contents are non-visible, and don't eat brushes
#define CONTENTS_AREAPORTAL 0x8000
#define CONTENTS_PLAYERCLIP 0x10000
#define CONTENTS_MONSTERCLIP 0x20000
// currents can be added to any other contents, and may be mixed
#define CONTENTS_CURRENT_0 0x40000
#define CONTENTS_CURRENT_90 0x80000
#define CONTENTS_CURRENT_180 0x100000
#define CONTENTS_CURRENT_270 0x200000
#define CONTENTS_CURRENT_UP 0x400000
#define CONTENTS_CURRENT_DOWN 0x800000
#define CONTENTS_ORIGIN 0x1000000 // removed before bsping an entity
#define CONTENTS_MONSTER 0x2000000 // should never be on a brush, only in game
#define CONTENTS_DEBRIS 0x4000000
#define CONTENTS_DETAIL 0x8000000 // brushes to be added after vis leafs
#define CONTENTS_TRANSLUCENT 0x10000000 // auto set if any surface has trans
#define CONTENTS_LADDER 0x20000000
#define CONTENTS_HITBOX 0x40000000 // use accurate hitboxes on trace
// NOTE: These are stored in a short in the engine now. Don't use more than 16 bits
#define SURF_LIGHT 0x0001 // value will hold the light strength
#define SURF_SKY2D 0x0002 // don't draw, indicates we should skylight + draw 2d sky but not draw the 3D skybox
#define SURF_SKY 0x0004 // don't draw, but add to skybox
#define SURF_WARP 0x0008 // turbulent water warp
#define SURF_TRANS 0x0010
#define SURF_NOPORTAL 0x0020 // the surface can not have a portal placed on it
#define SURF_TRIGGER 0x0040 // FIXME: This is an xbox hack to work around elimination of trigger surfaces, which breaks occluders
#define SURF_NODRAW 0x0080 // don't bother referencing the texture
#define SURF_HINT 0x0100 // make a primary bsp splitter
#define SURF_SKIP 0x0200 // completely ignore, allowing non-closed brushes
#define SURF_NOLIGHT 0x0400 // Don't calculate light
#define SURF_BUMPLIGHT 0x0800 // calculate three lightmaps for the surface for bumpmapping
#define SURF_NOSHADOWS 0x1000 // Don't receive shadows
#define SURF_NODECALS 0x2000 // Don't receive decals
#define SURF_NOPAINT SURF_NODECALS // the surface can not have paint placed on it
#define SURF_NOCHOP 0x4000 // Don't subdivide patches on this surface
#define SURF_HITBOX 0x8000 // surface is part of a hitbox
#define CONTENTS_CSGO_TEAM1 ( 1ull << LAYER_INDEX_CONTENTS_CSGO_TEAM1 )
#define CONTENTS_CSGO_TEAM2 ( 1ull << LAYER_INDEX_CONTENTS_CSGO_TEAM2 )
#define CONTENTS_CSGO_GRENADE_CLIP ( 1ull << LAYER_INDEX_CONTENTS_CSGO_GRENADE_CLIP )
#define CONTENTS_CSGO_DRONE_CLIP ( 1ull << LAYER_INDEX_CONTENTS_CSGO_DRONE_CLIP )
#define CONTENTS_CSGO_MOVEABLE ( 1ull << LAYER_INDEX_CONTENTS_CSGO_MOVEABLE )
#define CONTENTS_CSGO_OPAQUE ( 1ull << LAYER_INDEX_CONTENTS_CSGO_OPAQUE )
#define CONTENTS_CSGO_MONSTER ( 1ull << LAYER_INDEX_CONTENTS_CSGO_MONSTER )
#define CONTENTS_CSGO_UNUSED_LAYER ( 1ull << LAYER_INDEX_CONTENTS_CSGO_UNUSED_LAYER )
#define CONTENTS_CSGO_THROWN_GRENADE ( 1ull << LAYER_INDEX_CONTENTS_CSGO_THROWN_GRENADE )
// -----------------------------------------------------
// spatial content masks - used for spatial queries (traceline,etc.)
// -----------------------------------------------------
#define MASK_ALL (0xFFFFFFFF)
#define MASK_ALL (~0ull)
// everything that is normally solid
#define MASK_SOLID (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_MONSTER|CONTENTS_GRATE)
#define MASK_SOLID (CONTENTS_SOLID|CONTENTS_WINDOW|CONTENTS_PLAYER|CONTENTS_NPC|CONTENTS_PASS_BULLETS)
// everything that blocks player movement
#define MASK_PLAYERSOLID (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_PLAYERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER|CONTENTS_GRATE)
#define MASK_PLAYERSOLID (CONTENTS_SOLID|CONTENTS_PLAYER_CLIP|CONTENTS_WINDOW|CONTENTS_PLAYER|CONTENTS_NPC|CONTENTS_PASS_BULLETS)
// blocks npc movement
#define MASK_NPCSOLID (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_MONSTERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER|CONTENTS_GRATE)
#define MASK_NPCSOLID (CONTENTS_SOLID|CONTENTS_NPC_CLIP|CONTENTS_WINDOW|CONTENTS_PLAYER|CONTENTS_NPC|CONTENTS_PASS_BULLETS)
// blocks fluid movement
#define MASK_NPCFLUID (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_MONSTERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER)
#define MASK_NPCFLUID (CONTENTS_SOLID|CONTENTS_NPC_CLIP|CONTENTS_WINDOW|CONTENTS_PLAYER|CONTENTS_NPC)
// water physics in these contents
#define MASK_WATER (CONTENTS_WATER|CONTENTS_MOVEABLE|CONTENTS_SLIME)
// everything that blocks lighting
#define MASK_OPAQUE (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_OPAQUE)
// everything that blocks lighting, but with monsters added.
#define MASK_OPAQUE_AND_NPCS (MASK_OPAQUE|CONTENTS_MONSTER)
// everything that blocks line of sight for AI
#define MASK_BLOCKLOS (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_BLOCKLOS)
// everything that blocks line of sight for AI plus NPCs
#define MASK_BLOCKLOS_AND_NPCS (MASK_BLOCKLOS|CONTENTS_MONSTER)
// everything that blocks line of sight for players
#define MASK_VISIBLE (MASK_OPAQUE|CONTENTS_IGNORE_NODRAW_OPAQUE)
// everything that blocks line of sight for players, but with monsters added.
#define MASK_VISIBLE_AND_NPCS (MASK_OPAQUE_AND_NPCS|CONTENTS_IGNORE_NODRAW_OPAQUE)
#define MASK_WATER (CONTENTS_WATER|CONTENTS_SLIME)
// bullets see these as solid
#define MASK_SHOT (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_MONSTER|CONTENTS_WINDOW|CONTENTS_DEBRIS|CONTENTS_HITBOX)
#define MASK_SHOT (CONTENTS_SOLID|CONTENTS_PLAYER|CONTENTS_NPC|CONTENTS_WINDOW|CONTENTS_DEBRIS|CONTENTS_HITBOX)
// bullets see these as solid, except monsters (world+brush only)
#define MASK_SHOT_BRUSHONLY (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_DEBRIS)
#define MASK_SHOT_BRUSHONLY (CONTENTS_SOLID|CONTENTS_WINDOW|CONTENTS_DEBRIS)
// non-raycasted weapons see this as solid (includes grates)
#define MASK_SHOT_HULL (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_MONSTER|CONTENTS_WINDOW|CONTENTS_DEBRIS|CONTENTS_GRATE)
#define MASK_SHOT_HULL (CONTENTS_SOLID|CONTENTS_PLAYER|CONTENTS_NPC|CONTENTS_WINDOW|CONTENTS_DEBRIS|CONTENTS_PASS_BULLETS)
// hits solids (not grates) and passes through everything else
#define MASK_SHOT_PORTAL (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_MONSTER)
#define MASK_SHOT_PORTAL (CONTENTS_SOLID|CONTENTS_WINDOW|CONTENTS_PLAYER|CONTENTS_NPC)
// everything normally solid, except monsters (world+brush only)
#define MASK_SOLID_BRUSHONLY (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_GRATE)
#define MASK_SOLID_BRUSHONLY (CONTENTS_SOLID|CONTENTS_WINDOW|CONTENTS_PASS_BULLETS)
// everything normally solid for player movement, except monsters (world+brush only)
#define MASK_PLAYERSOLID_BRUSHONLY (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_PLAYERCLIP|CONTENTS_GRATE)
#define MASK_PLAYERSOLID_BRUSHONLY (CONTENTS_SOLID|CONTENTS_WINDOW|CONTENTS_PLAYER_CLIP|CONTENTS_PASS_BULLETS)
// everything normally solid for npc movement, except monsters (world+brush only)
#define MASK_NPCSOLID_BRUSHONLY (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_MONSTERCLIP|CONTENTS_GRATE)
// just the world, used for route rebuilding
#define MASK_NPCWORLDSTATIC (CONTENTS_SOLID|CONTENTS_WINDOW|CONTENTS_MONSTERCLIP|CONTENTS_GRATE)
// just the world, used for route rebuilding
#define MASK_NPCWORLDSTATIC_FLUID (CONTENTS_SOLID|CONTENTS_WINDOW|CONTENTS_MONSTERCLIP)
// These are things that can split areaportals
#define MASK_SPLITAREAPORTAL (CONTENTS_WATER|CONTENTS_SLIME)
// UNDONE: This is untested, any moving water
#define MASK_CURRENT (CONTENTS_CURRENT_0|CONTENTS_CURRENT_90|CONTENTS_CURRENT_180|CONTENTS_CURRENT_270|CONTENTS_CURRENT_UP|CONTENTS_CURRENT_DOWN)
// everything that blocks corpse movement
// UNDONE: Not used yet / may be deleted
#define MASK_DEADSOLID (CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_WINDOW|CONTENTS_GRATE)
#define MASK_NPCSOLID_BRUSHONLY (CONTENTS_SOLID|CONTENTS_WINDOW|CONTENTS_NPC_CLIP|CONTENTS_PASS_BULLETS)
#endif // BSPFLAGS_H

View File

@ -38,6 +38,15 @@ COLLISION DETECTION
#include "vcollide.h"
enum RayType_t : uint8
{
RAY_TYPE_LINE = 0,
RAY_TYPE_SPHERE,
RAY_TYPE_HULL,
RAY_TYPE_CAPSULE,
RAY_TYPE_MESH,
};
struct cmodel_t
{
Vector mins, maxs;
@ -59,70 +68,121 @@ struct csurface_t
//-----------------------------------------------------------------------------
struct Ray_t
{
VectorAligned m_Start; // starting point, centered within the extents
VectorAligned m_Delta; // direction + length of the ray
VectorAligned m_StartOffset; // Add this to m_Start to get the actual ray start
VectorAligned m_Extents; // Describes an axis aligned box extruded along a ray
const matrix3x4_t *m_pWorldAxisTransform;
bool m_IsRay; // are the extents zero?
bool m_IsSwept; // is delta != 0?
Ray_t() : m_pWorldAxisTransform( NULL ) {}
void Init( Vector const& start, Vector const& end )
Ray_t() { Init( Vector( 0.0f, 0.0f, 0.0f ) ); }
Ray_t( const Vector& vStartOffset ) { Init( vStartOffset ); }
Ray_t( const Vector& vCenter, float flRadius ) { Init( vCenter, flRadius ); }
Ray_t( const Vector& vMins, const Vector& vMaxs ) { Init( vMins, vMaxs ); }
Ray_t( const Vector& vCenterA, const Vector& vCenterB, float flRadius ) { Init( vCenterA, vCenterB, flRadius ); }
Ray_t( const Vector& vMins, const Vector& vMaxs, const Vector* pVertices, int nNumVertices ) { Init( vMins, vMaxs, pVertices, nNumVertices ); }
void Init( const Vector& vStartOffset )
{
Assert( &end );
VectorSubtract( end, start, m_Delta );
m_IsSwept = (m_Delta.LengthSqr() != 0);
VectorClear( m_Extents );
m_pWorldAxisTransform = NULL;
m_IsRay = true;
// Offset m_Start to be in the center of the box...
VectorClear( m_StartOffset );
VectorCopy( start, m_Start );
m_Line.m_vStartOffset = vStartOffset;
m_Line.m_flRadius = 0.0f;
m_eType = RAY_TYPE_LINE;
}
void Init( Vector const& start, Vector const& end, Vector const& mins, Vector const& maxs )
void Init( const Vector& vCenter, float flRadius )
{
Assert( &end );
VectorSubtract( end, start, m_Delta );
m_pWorldAxisTransform = NULL;
m_IsSwept = (m_Delta.LengthSqr() != 0);
VectorSubtract( maxs, mins, m_Extents );
m_Extents *= 0.5f;
m_IsRay = (m_Extents.LengthSqr() < 1e-6);
// Offset m_Start to be in the center of the box...
VectorAdd( mins, maxs, m_StartOffset );
m_StartOffset *= 0.5f;
VectorAdd( start, m_StartOffset, m_Start );
m_StartOffset *= -1.0f;
}
// compute inverse delta
Vector InvDelta() const
{
Vector vecInvDelta;
for ( int iAxis = 0; iAxis < 3; ++iAxis )
if ( flRadius > 0.0f )
{
if ( m_Delta[iAxis] != 0.0f )
m_Sphere.m_vCenter = vCenter;
m_Sphere.m_flRadius = flRadius;
m_eType = RAY_TYPE_SPHERE;
}
else
{
Init( vCenter );
}
}
void Init( const Vector& vMins, const Vector& vMaxs )
{
if ( vMins != vMaxs )
{
m_Hull.m_vMins = vMins;
m_Hull.m_vMaxs = vMaxs;
m_eType = RAY_TYPE_HULL;
}
else
{
Init( vMins );
}
}
void Init( const Vector& vCenterA, const Vector& vCenterB, float flRadius )
{
if ( vCenterA != vCenterB )
{
if ( flRadius > 0.0f )
{
vecInvDelta[iAxis] = 1.0f / m_Delta[iAxis];
m_Capsule.m_vCenter[0] = vCenterA;
m_Capsule.m_vCenter[1] = vCenterB;
m_Capsule.m_flRadius = flRadius;
m_eType = RAY_TYPE_CAPSULE;
}
else
{
vecInvDelta[iAxis] = FLT_MAX;
Init( vCenterA, vCenterB );
}
}
return vecInvDelta;
else
{
Init( vCenterA, flRadius );
}
}
private:
void Init( const Vector& vMins, const Vector& vMaxs, const Vector* pVertices, int nNumVertices )
{
m_Mesh.m_vMins = vMins;
m_Mesh.m_vMaxs = vMaxs;
m_Mesh.m_pVertices = pVertices;
m_Mesh.m_nNumVertices = nNumVertices;
m_eType = RAY_TYPE_MESH;
}
struct Line_t
{
Vector m_vStartOffset;
float m_flRadius;
};
struct Sphere_t
{
Vector m_vCenter;
float m_flRadius;
};
struct Hull_t
{
Vector m_vMins;
Vector m_vMaxs;
};
struct Capsule_t
{
Vector m_vCenter[2];
float m_flRadius;
};
struct Mesh_t
{
Vector m_vMins;
Vector m_vMaxs;
const Vector* m_pVertices;
int m_nNumVertices;
};
union
{
Line_t m_Line;
Sphere_t m_Sphere;
Hull_t m_Hull;
Capsule_t m_Capsule;
Mesh_t m_Mesh;
};
RayType_t m_eType;
};

View File

@ -352,13 +352,81 @@ enum RenderFx_t : unsigned char
kRenderFxMax
};
enum Collision_Group_t
enum BuiltInInteractionLayer_t
{
COLLISION_GROUP_ALWAYS = 0,
COLLISION_GROUP_NEVER,
COLLISION_GROUP_TRIGGER,
COLLISION_GROUP_CONDITIONALLY_SOLID,
COLLISION_GROUP_DEFAULT,
LAYER_INDEX_CONTENTS_SOLID = 0,
LAYER_INDEX_CONTENTS_HITBOX,
LAYER_INDEX_CONTENTS_TRIGGER,
LAYER_INDEX_CONTENTS_SKY,
LAYER_INDEX_FIRST_USER,
LAYER_INDEX_NOT_FOUND = -1,
LAYER_INDEX_MAX_ALLOWED = 64,
};
enum StandardInteractionLayers_t
{
LAYER_INDEX_CONTENTS_PLAYER_CLIP = LAYER_INDEX_FIRST_USER,
LAYER_INDEX_CONTENTS_NPC_CLIP,
LAYER_INDEX_CONTENTS_BLOCK_LOS,
LAYER_INDEX_CONTENTS_BLOCK_LIGHT,
LAYER_INDEX_CONTENTS_LADDER,
LAYER_INDEX_CONTENTS_PICKUP,
LAYER_INDEX_CONTENTS_BLOCK_SOUND,
LAYER_INDEX_CONTENTS_NODRAW,
LAYER_INDEX_CONTENTS_WINDOW,
LAYER_INDEX_CONTENTS_PASS_BULLETS,
LAYER_INDEX_CONTENTS_WORLD_GEOMETRY,
LAYER_INDEX_CONTENTS_WATER,
LAYER_INDEX_CONTENTS_SLIME,
LAYER_INDEX_CONTENTS_TOUCH_ALL,
LAYER_INDEX_CONTENTS_PLAYER,
LAYER_INDEX_CONTENTS_NPC,
LAYER_INDEX_CONTENTS_DEBRIS,
LAYER_INDEX_CONTENTS_PHYSICS_PROP,
LAYER_INDEX_CONTENTS_NAV_IGNORE,
LAYER_INDEX_CONTENTS_NAV_LOCAL_IGNORE,
LAYER_INDEX_CONTENTS_POST_PROCESSING_VOLUME,
LAYER_INDEX_CONTENTS_UNUSED_LAYER3,
LAYER_INDEX_CONTENTS_CARRIED_OBJECT,
LAYER_INDEX_CONTENTS_PUSHAWAY,
LAYER_INDEX_CONTENTS_SERVER_ENTITY_ON_CLIENT,
LAYER_INDEX_CONTENTS_CARRIED_WEAPON,
LAYER_INDEX_CONTENTS_STATIC_LEVEL,
LAYER_INDEX_FIRST_MOD_SPECIFIC,
};
enum ModSpecificInteractionLayers_t
{
LAYER_INDEX_CONTENTS_CSGO_TEAM1 = LAYER_INDEX_FIRST_MOD_SPECIFIC,
LAYER_INDEX_CONTENTS_CSGO_TEAM2,
LAYER_INDEX_CONTENTS_CSGO_GRENADE_CLIP,
LAYER_INDEX_CONTENTS_CSGO_DRONE_CLIP,
LAYER_INDEX_CONTENTS_CSGO_MOVEABLE,
LAYER_INDEX_CONTENTS_CSGO_OPAQUE,
LAYER_INDEX_CONTENTS_CSGO_MONSTER,
LAYER_INDEX_CONTENTS_CSGO_UNUSED_LAYER,
LAYER_INDEX_CONTENTS_CSGO_THROWN_GRENADE,
};
enum BuiltInCollisionGroup_t
{
// Default layer, always collides with everything.
COLLISION_GROUP_ALWAYS = 0, // "always"
// This is how you turn off all collisions for an object - move it to this group
COLLISION_GROUP_NONPHYSICAL, // "never"
// Trigger layer, never collides with anything, only triggers/interacts. Use when querying for interaction layers.
COLLISION_GROUP_TRIGGER, // "trigger"
// Conditionally solid means that the collision response will be zero or as defined in the table when there are matching interactions
COLLISION_GROUP_CONDITIONALLY_SOLID, // needs interactions
// First unreserved collision layer index.
COLLISION_GROUP_FIRST_USER,
// Hard limit of 254 due to memory layout, and these are never visible to scene queries.
COLLISION_GROUPS_MAX_ALLOWED = 64,
};
enum StandardCollisionGroups_t
{
COLLISION_GROUP_DEFAULT = COLLISION_GROUP_FIRST_USER,
COLLISION_GROUP_DEBRIS, // Collides with nothing but world, static stuff and triggers
COLLISION_GROUP_INTERACTIVE_DEBRIS, // Collides with everything except other interactive debris or debris
COLLISION_GROUP_INTERACTIVE, // Collides with everything except interactive debris or debris
@ -378,14 +446,11 @@ enum Collision_Group_t
COLLISION_GROUP_PUSHAWAY, // Nonsolid on client and server, pushaway in player code
COLLISION_GROUP_NPC_ACTOR, // Used so NPCs in scripts ignore the player.
COLLISION_GROUP_NPC_SCRIPTED, // USed for NPCs in scripts that should not collide with each other
COLLISION_GROUP_NPC_SCRIPTED, // Used for NPCs in scripts that should not collide with each other
COLLISION_GROUP_PZ_CLIP,
COLLISION_GROUP_PROPS,
LAST_SHARED_COLLISION_GROUP
LAST_SHARED_COLLISION_GROUP,
};
#include "basetypes.h"

View File

@ -1,233 +0,0 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#ifndef ENGINE_IENGINETRACE_H
#define ENGINE_IENGINETRACE_H
#ifdef _WIN32
#pragma once
#endif
#include "entityhandle.h"
#include "utlvector.h" //need CUtlVector for IEngineTrace::GetBrushesIn*()
#include "mathlib/vector4d.h"
#include "bspflags.h"
class Vector;
class CEntityInstance;
struct Ray_t;
class CGameTrace;
typedef CGameTrace trace_t;
class ICollideable;
class QAngle;
class ITraceListData;
class CPhysCollide;
struct cplane_t;
struct virtualmeshlist_t;
//-----------------------------------------------------------------------------
// The standard trace filter... NOTE: Most normal traces inherit from CTraceFilter!!!
//-----------------------------------------------------------------------------
enum TraceType_t
{
TRACE_EVERYTHING = 0,
TRACE_WORLD_ONLY, // NOTE: This does *not* test static props!!!
TRACE_ENTITIES_ONLY, // NOTE: This version will *not* test static props
TRACE_EVERYTHING_FILTER_PROPS, // NOTE: This version will pass the IHandleEntity for props through the filter, unlike all other filters
};
abstract_class ITraceFilter
{
public:
virtual bool ShouldHitEntity( CEntityInstance *pEntity, int contentsMask ) = 0;
virtual TraceType_t GetTraceType() const = 0;
};
//-----------------------------------------------------------------------------
// Classes are expected to inherit these + implement the ShouldHitEntity method
//-----------------------------------------------------------------------------
// This is the one most normal traces will inherit from
class CTraceFilter : public ITraceFilter
{
public:
virtual TraceType_t GetTraceType() const
{
return TRACE_EVERYTHING;
}
};
class CTraceFilterEntitiesOnly : public ITraceFilter
{
public:
virtual TraceType_t GetTraceType() const
{
return TRACE_ENTITIES_ONLY;
}
};
//-----------------------------------------------------------------------------
// Classes need not inherit from these
//-----------------------------------------------------------------------------
class CTraceFilterWorldOnly : public ITraceFilter
{
public:
bool ShouldHitEntity( CEntityInstance *pServerEntity, int contentsMask )
{
return false;
}
virtual TraceType_t GetTraceType() const
{
return TRACE_WORLD_ONLY;
}
};
class CTraceFilterWorldAndPropsOnly : public ITraceFilter
{
public:
bool ShouldHitEntity( CEntityInstance *pServerEntity, int contentsMask )
{
return false;
}
virtual TraceType_t GetTraceType() const
{
return TRACE_EVERYTHING;
}
};
class CTraceFilterHitAll : public CTraceFilter
{
public:
virtual bool ShouldHitEntity( CEntityInstance *pServerEntity, int contentsMask )
{
return true;
}
};
enum DebugTraceCounterBehavior_t
{
kTRACE_COUNTER_SET = 0,
kTRACE_COUNTER_INC,
};
//-----------------------------------------------------------------------------
// Enumeration interface for EnumerateLinkEntities
//-----------------------------------------------------------------------------
abstract_class IEntityEnumerator
{
public:
// This gets called with each handle
virtual bool EnumEntity( CEntityInstance *pHandleEntity ) = 0;
};
struct BrushSideInfo_t
{
Vector4D plane; // The plane of the brush side
unsigned short bevel; // Bevel plane?
unsigned short thin; // Thin?
};
//-----------------------------------------------------------------------------
// Interface the engine exposes to the game DLL
//-----------------------------------------------------------------------------
#define INTERFACEVERSION_ENGINETRACE_SERVER "EngineTraceServer004"
#define INTERFACEVERSION_ENGINETRACE_CLIENT "EngineTraceClient004"
abstract_class IEngineTrace
{
public:
// Returns the contents mask + entity at a particular world-space position
virtual int GetPointContents( const Vector &vecAbsPosition, int contentsMask = MASK_ALL, CEntityInstance** ppEntity = NULL ) = 0;
// Returns the contents mask of the world only @ the world-space position (static props are ignored)
virtual int GetPointContents_WorldOnly( const Vector &vecAbsPosition, int contentsMask = MASK_ALL ) = 0;
// Get the point contents, but only test the specific entity. This works
// on static props and brush models.
//
// If the entity isn't a static prop or a brush model, it returns CONTENTS_EMPTY and sets
// bFailed to true if bFailed is non-null.
virtual int GetPointContents_Collideable( ICollideable *pCollide, const Vector &vecAbsPosition ) = 0;
// Traces a ray against a particular entity
virtual void ClipRayToEntity( const Ray_t &ray, unsigned int fMask, CEntityInstance *pEnt, trace_t *pTrace ) = 0;
// Traces a ray against a particular entity
virtual void ClipRayToCollideable( const Ray_t &ray, unsigned int fMask, ICollideable *pCollide, trace_t *pTrace ) = 0;
// A version that simply accepts a ray (can work as a traceline or tracehull)
virtual void TraceRay( const Ray_t &ray, unsigned int fMask, ITraceFilter *pTraceFilter, trace_t *pTrace ) = 0;
// A version that sets up the leaf and entity lists and allows you to pass those in for collision.
virtual void SetupLeafAndEntityListRay( const Ray_t &ray, ITraceListData *pTraceData ) = 0;
virtual void SetupLeafAndEntityListBox( const Vector &vecBoxMin, const Vector &vecBoxMax, ITraceListData *pTraceData ) = 0;
virtual void TraceRayAgainstLeafAndEntityList( const Ray_t &ray, ITraceListData *pTraceData, unsigned int fMask, ITraceFilter *pTraceFilter, trace_t *pTrace ) = 0;
// A version that sweeps a collideable through the world
// abs start + abs end represents the collision origins you want to sweep the collideable through
// vecAngles represents the collision angles of the collideable during the sweep
virtual void SweepCollideable( ICollideable *pCollide, const Vector &vecAbsStart, const Vector &vecAbsEnd,
const QAngle &vecAngles, unsigned int fMask, ITraceFilter *pTraceFilter, trace_t *pTrace ) = 0;
// Enumerates over all entities along a ray
// If triggers == true, it enumerates all triggers along a ray
virtual void EnumerateEntities( const Ray_t &ray, bool triggers, IEntityEnumerator *pEnumerator ) = 0;
// Same thing, but enumerate entitys within a box
virtual void EnumerateEntities( const Vector &vecAbsMins, const Vector &vecAbsMaxs, IEntityEnumerator *pEnumerator ) = 0;
// Convert a handle entity to a collideable. Useful inside enumer
virtual ICollideable *GetCollideable( CEntityInstance *pEntity ) = 0;
// HACKHACK: Temp for performance measurments
virtual int GetStatByIndex( int index, bool bClear ) = 0;
//finds brushes in an AABB, prone to some false positives
virtual void GetBrushesInAABB( const Vector &vMins, const Vector &vMaxs, CUtlVector<int> *pOutput, int iContentsMask = 0xFFFFFFFF ) = 0;
//Creates a CPhysCollide out of all displacements wholly or partially contained in the specified AABB
virtual CPhysCollide* GetCollidableFromDisplacementsInAABB( const Vector& vMins, const Vector& vMaxs ) = 0;
// gets the number of displacements in the world
virtual int GetNumDisplacements( ) = 0;
// gets a specific diplacement mesh
virtual void GetDisplacementMesh( int nIndex, virtualmeshlist_t *pMeshTriList ) = 0;
//retrieve brush planes and contents, returns true if data is being returned in the output pointers, false if the brush doesn't exist
virtual bool GetBrushInfo( int iBrush, CUtlVector<BrushSideInfo_t> *pBrushSideInfoOut, int *pContentsOut ) = 0;
virtual bool PointOutsideWorld( const Vector &ptTest ) = 0; //Tests a point to see if it's outside any playable area
// Walks bsp to find the leaf containing the specified point
virtual int GetLeafContainingPoint( const Vector &ptTest ) = 0;
virtual ITraceListData *AllocTraceListData() = 0;
virtual void FreeTraceListData(ITraceListData *) = 0;
/// Used only in debugging: get/set/clear/increment the trace debug counter. See comment below for details.
virtual int GetSetDebugTraceCounter( int value, DebugTraceCounterBehavior_t behavior ) = 0;
};
/// IEngineTrace::GetSetDebugTraceCounter
/// SET to a negative number to disable. SET to a positive number to reset the counter; it'll tick down by
/// one for each trace, and break into the debugger on hitting zero. INC lets you add or subtract from the
/// counter. In each case it will return the value of the counter BEFORE you set or incremented it. INC 0
/// to query. This end-around approach is necessary for security: because only the engine knows when we
/// are in a trace, and only the server knows when we are in a think, data must somehow be shared between
/// them. Simply returning a pointer to an address inside the engine in a retail build is unacceptable,
/// and in the PC there is no way to distinguish between retail and non-retail builds at compile time
/// (there is no #define for it).
/// This may seem redundant with the VPROF_INCREMENT_COUNTER( "TraceRay" ), but it's not, because while
/// that's readable across DLLs, there's no way to trap on its exceeding a certain value, nor can we reset
/// it for each think.
#endif // ENGINE_IENGINETRACE_H

View File

@ -12,84 +12,488 @@
#include "cmodel.h"
#include "Color.h"
#include "entity2/entityinstance.h"
#include "mathlib/transform.h"
#include "tier1/generichash.h"
#include "tier1/utlvector.h"
#include "tier1/utlstring.h"
#include "ispatialpartition.h"
#if defined( CLIENT_DLL )
class C_BaseEntity;
#else
class CBaseEntity;
#endif
class IPhysicsBody;
class IPhysicsShape;
typedef IPhysicsBody* HPhysicsBody;
typedef IPhysicsShape* HPhysicsShape;
//-----------------------------------------------------------------------------
// Purpose: A trace is returned when a box is swept through the world
// NOTE: eventually more of this class should be moved up into the base class!!
//-----------------------------------------------------------------------------
class CGameTrace : public CBaseTrace
enum CollisionFunctionMask_t
{
FCOLLISION_FUNC_ENABLE_SOLID_CONTACT = (1<<0),
FCOLLISION_FUNC_ENABLE_TRACE_QUERY = (1<<1),
FCOLLISION_FUNC_ENABLE_TOUCH_EVENT = (1<<2),
FCOLLISION_FUNC_ENABLE_SELF_COLLISIONS = (1<<3),
FCOLLISION_FUNC_IGNORE_FOR_HITBOX_TEST = (1<<4),
FCOLLISION_FUNC_ENABLE_TOUCH_PERSISTS = (1<<5),
};
// these are on by default
#define FCOLLISION_FUNC_DEFAULT (FCOLLISION_FUNC_ENABLE_SOLID_CONTACT | FCOLLISION_FUNC_ENABLE_TRACE_QUERY | FCOLLISION_FUNC_ENABLE_TOUCH_EVENT)
enum RnQueryObjectSet
{
RNQUERY_OBJECTS_STATIC = (1<<0),
RNQUERY_OBJECTS_DYNAMIC = (1<<1),
RNQUERY_OBJECTS_NON_COLLIDEABLE = (1<<2),
RNQUERY_OBJECTS_KEYFRAMED_ONLY = (1<<3) | (1<<8),
RNQUERY_OBJECTS_DYNAMIC_ONLY = (1<<4) | (1<<8),
RNQUERY_OBJECTS_ALL_GAME_ENTITIES = RNQUERY_OBJECTS_DYNAMIC | RNQUERY_OBJECTS_NON_COLLIDEABLE,
RNQUERY_OBJECTS_ALL = RNQUERY_OBJECTS_STATIC | RNQUERY_OBJECTS_ALL_GAME_ENTITIES,
};
enum HitGroup_t
{
HITGROUP_INVALID = -1,
HITGROUP_GENERIC = 0,
HITGROUP_HEAD,
HITGROUP_CHEST,
HITGROUP_STOMACH,
HITGROUP_LEFTARM,
HITGROUP_RIGHTARM,
HITGROUP_LEFTLEG,
HITGROUP_RIGHTLEG,
HITGROUP_NECK,
HITGROUP_UNUSED,
HITGROUP_GEAR,
HITGROUP_SPECIAL,
HITGROUP_COUNT,
};
enum HitboxShapeType_t
{
HITBOX_SHAPE_HULL = 0,
HITBOX_SHAPE_SPHERE,
HITBOX_SHAPE_CAPSULE,
};
class CPhysSurfacePropertiesPhysics
{
public:
// Returns true if hEnt points at the world entity.
// If this returns true, then you can't use GetHitBoxIndex().
bool DidHitWorld() const;
CPhysSurfacePropertiesPhysics()
{
m_friction = 0.0f;
m_elasticity = 0.0f;
m_density = 0.0f;
m_thickness = 0.1f;
m_softContactFrequency = 0.0f;
m_softContactDampingRatio = 0.0f;
m_wheelDrag = 0.0f;
}
// Returns true if we hit something and it wasn't the world.
bool DidHitNonWorldEntity() const;
// Gets the entity's network index if the trace has hit an entity.
// If not, returns -1.
int GetEntityIndex() const;
// Returns true if there was any kind of impact at all
bool DidHit() const;
// The engine doesn't know what a CBaseEntity is, so it has a backdoor to
// let it get at the edict.
#if defined( ENGINE_DLL )
void SetEdict( edict_t *pEdict );
edict_t* GetEdict() const;
#endif
public:
float m_friction;
float m_elasticity;
float m_density;
float m_thickness;
float m_softContactFrequency;
float m_softContactDampingRatio;
float m_wheelDrag;
};
float fractionleftsolid; // time we left a solid, only valid if we started in solid
csurface_t surface; // surface hit (impact surface)
class CPhysSurfacePropertiesSoundNames
{
public:
CPhysSurfacePropertiesSoundNames()
{
m_meleeImpact = "";
m_pushOff = "";
m_skidStop = "";
}
public:
CUtlString m_impactSoft;
CUtlString m_impactHard;
CUtlString m_scrapeSmooth;
CUtlString m_scrapeRough;
CUtlString m_bulletImpact;
CUtlString m_rolling;
CUtlString m_break;
CUtlString m_strain;
CUtlString m_meleeImpact;
CUtlString m_pushOff;
CUtlString m_skidStop;
};
int hitgroup; // 0 == generic, non-zero is specific body part
class CPhysSurfacePropertiesAudio
{
public:
CPhysSurfacePropertiesAudio()
{
m_reflectivity = 0.0f;
m_hardnessFactor = 0.0f;
m_roughnessFactor = 0.0f;
m_roughThreshold = 0.0f;
m_hardThreshold = 0.0f;
m_hardVelocityThreshold = 0.0f;
m_flStaticImpactVolume = 0.0f;
m_flOcclusionFactor = 0.0f;
}
public:
float m_reflectivity;
float m_hardnessFactor;
float m_roughnessFactor;
float m_roughThreshold;
float m_hardThreshold;
float m_hardVelocityThreshold;
float m_flStaticImpactVolume;
float m_flOcclusionFactor;
};
short physicsbone; // physics bone hit by trace in studio
unsigned short worldSurfaceIndex; // Index of the msurface2_t, if applicable
class CPhysSurfaceProperties
{
public:
CPhysSurfaceProperties()
{
m_bHidden = false;
}
public:
CUtlString m_name;
uint32 m_nameHash;
uint32 m_baseNameHash;
int32 m_nListIndex;
int32 m_nBaseListIndex;
bool m_bHidden;
CUtlString m_description;
CPhysSurfacePropertiesPhysics m_physics;
CPhysSurfacePropertiesSoundNames m_audioSounds;
CPhysSurfacePropertiesAudio m_audioParams;
};
#if defined( CLIENT_DLL )
C_BaseEntity *m_pEnt;
#else
CBaseEntity *m_pEnt;
class CHitBox
{
public:
CHitBox()
{
m_vMinBounds.Init();
m_vMaxBounds.Init();
m_nBoneNameHash = 0;
m_nGroupId = HITGROUP_GENERIC;
m_nShapeType = HITBOX_SHAPE_HULL;
m_bTranslationOnly = false;
m_CRC = 0;
m_cRenderColor.SetColor( 255, 255, 255, 255 );
m_nHitBoxIndex = 0;
m_bForcedTransform = false;
m_forcedTransform.SetToIdentity();
}
public:
CUtlString m_name;
CUtlString m_sSurfaceProperty;
CUtlString m_sBoneName;
Vector m_vMinBounds;
Vector m_vMaxBounds;
float m_flShapeRadius;
uint32 m_nBoneNameHash;
int32 m_nGroupId;
uint8 m_nShapeType;
bool m_bTranslationOnly;
uint32 m_CRC;
Color m_cRenderColor;
uint16 m_nHitBoxIndex;
bool m_bForcedTransform;
CTransform m_forcedTransform;
};
class CDefaultHitbox : public CHitBox
{
public:
CDefaultHitbox()
{
V_strncpy( m_tempName, "invalid_hitbox", sizeof( m_tempName ) );
V_strncpy( m_tempBoneName, "invalid_bone", sizeof( m_tempBoneName ) );
V_strncpy( m_tempSurfaceProp, "default", sizeof( m_tempSurfaceProp ) );
m_name = m_tempName;
m_sSurfaceProperty = m_tempSurfaceProp;
m_sBoneName = m_tempBoneName;
m_nBoneNameHash = MurmurHash2LowerCase(m_tempBoneName, 0x31415926);
#if 0
if (g_bUpdateStringTokenDatabase)
{
RegisterStringToken(m_nBoneNameHash, m_tempBoneName, 0, true);
}
#endif
// NOTE: this member is overloaded.
// If hEnt points at the world entity, then this is the static prop index.
// Otherwise, this is the hitbox index.
int hitbox; // box hit by trace in studio
m_cRenderColor.SetColor( 0, 0, 0, 0 );
}
public:
char m_tempName[16];
char m_tempBoneName[16];
char m_tempSurfaceProp[16];
};
CGameTrace() {}
struct RnQueryShapeAttr_t
{
public:
RnQueryShapeAttr_t()
{
m_nInteractsWith = 0;
m_nInteractsExclude = 0;
m_nInteractsAs = 0;
m_nEntityIdsToIgnore[0] = -1;
m_nEntityIdsToIgnore[1] = -1;
m_nOwnerIdsToIgnore[0] = -1;
m_nOwnerIdsToIgnore[1] = -1;
m_nHierarchyIds[0] = 0;
m_nHierarchyIds[1] = 0;
m_nObjectSetMask = RNQUERY_OBJECTS_ALL;
m_nCollisionGroup = COLLISION_GROUP_ALWAYS;
m_bHitSolid = true;
m_bHitSolidRequiresGenerateContacts = false;
m_bHitTrigger = false;
m_bShouldIgnoreDisabledPairs = true;
m_bIgnoreIfBothInteractWithHitboxes = false;
m_bForceHitEverything = false;
m_bUnknown = true;
}
bool HasInteractsAsLayer( int nLayerIndex ) const { return ( m_nInteractsAs & ( 1ull << nLayerIndex ) ) != 0; }
bool HasInteractsWithLayer( int nLayerIndex ) const { return ( m_nInteractsWith & ( 1ull << nLayerIndex ) ) != 0; }
bool HasInteractsExcludeLayer( int nLayerIndex ) const { return ( m_nInteractsExclude & ( 1ull << nLayerIndex ) ) != 0; }
void EnableInteractsAsLayer( int nLayer ) { m_nInteractsAs |= ( 1ull << nLayer ); }
void EnableInteractsWithLayer( int nLayer ) { m_nInteractsWith |= ( 1ull << nLayer ); }
void EnableInteractsExcludeLayer( int nLayer ) { m_nInteractsExclude |= ( 1ull << nLayer ); }
void DisableInteractsAsLayer( int nLayer ) { m_nInteractsAs &= ~( 1ull << nLayer ); }
void DisableInteractsWithLayer( int nLayer ) { m_nInteractsWith &= ~( 1ull << nLayer ); }
void DisableInteractsExcludeLayer( int nLayer ) { m_nInteractsExclude &= ~( 1ull << nLayer ); }
public:
// Which interaction layers do I interact or collide with? (e.g. I collide with LAYER_INDEX_CONTENTS_PASS_BULLETS because I am not a bullet)
// NOTE: This is analogous to the "solid mask" or "trace mask" in source 1 (bit mask of CONTENTS_* or 1<<LAYER_INDEX_*)
uint64 m_nInteractsWith;
// Which interaction layers do I _not_ interact or collide with? If my exclusion layers match m_nInteractsAs on the other object then no interaction happens.
uint64 m_nInteractsExclude;
// Which interaction layers do I represent? (e.g. I am a LAYER_INDEX_CONTENTS_PLAYER_CLIP volume)
// NOTE: This is analogous to "contents" in source 1 (bit mask of CONTENTS_* or 1<<LAYER_INDEX_*)
uint64 m_nInteractsAs;
uint32 m_nEntityIdsToIgnore[2]; // this is the ID of the game entity which should be ignored
uint32 m_nOwnerIdsToIgnore[2]; // this is the ID of the owner of the game entity which should be ignored
uint16 m_nHierarchyIds[2]; // this is an ID for the hierarchy of game entities (used to disable collision among objects in a hierarchy)
uint16 m_nObjectSetMask; // set of RnQueryObjectSet bits
uint8 m_nCollisionGroup; // one of the registered collision groups
bool m_bHitSolid : 1; // if true, then query will hit solid
bool m_bHitSolidRequiresGenerateContacts : 1; // if true, the FCOLLISION_FUNC_ENABLE_SOLID_CONTACT flag will be checked to hit solid
bool m_bHitTrigger : 1; // if true, then query will hit tirgger
bool m_bShouldIgnoreDisabledPairs : 1; // if true, then ignores if the query and shape entity IDs are in collision pairs
bool m_bIgnoreIfBothInteractWithHitboxes : 1; // if true, then ignores if both query and shape interact with LAYER_INDEX_CONTENTS_HITBOX
bool m_bForceHitEverything : 1; // if true, will hit any objects without any conditions
bool m_bUnknown : 1; // haven't found where this is used yet
};
struct RnQueryAttr_t : public RnQueryShapeAttr_t
{
};
class CTraceFilter : public RnQueryAttr_t
{
public:
CTraceFilter( uint64 nInteractsWith = 0, int nCollisionGroup = COLLISION_GROUP_DEFAULT, bool bIterateEntities = true )
{
m_nInteractsWith = nInteractsWith;
m_nCollisionGroup = nCollisionGroup;
m_bIterateEntities = bIterateEntities;
}
CTraceFilter( CEntityInstance* pPassEntity,
CEntityInstance* pPassEntityOwner,
uint16 nHierarchyId,
uint64 nInteractsWith = 0,
int nCollisionGroup = COLLISION_GROUP_DEFAULT,
bool bIterateEntities = true )
{
SetPassEntity1( pPassEntity );
SetPassEntityOwner1( pPassEntityOwner );
m_nHierarchyIds[0] = nHierarchyId;
m_nInteractsWith = nInteractsWith;
m_nCollisionGroup = nCollisionGroup;
m_bIterateEntities = bIterateEntities;
}
CTraceFilter( CEntityInstance* pPassEntity1,
CEntityInstance* pPassEntity2,
CEntityInstance* pPassEntityOwner1,
CEntityInstance* pPassEntityOwner2,
uint16 nHierarchyId1,
uint16 nHierarchyId2,
uint64 nInteractsWith = 0,
int nCollisionGroup = COLLISION_GROUP_DEFAULT,
bool bIterateEntities = true )
{
SetPassEntity1( pPassEntity1 );
SetPassEntity2( pPassEntity2 );
SetPassEntityOwner1( pPassEntityOwner1 );
SetPassEntityOwner2( pPassEntityOwner2 );
m_nHierarchyIds[0] = nHierarchyId1;
m_nHierarchyIds[1] = nHierarchyId2;
m_nInteractsWith = nInteractsWith;
m_nCollisionGroup = nCollisionGroup;
m_bIterateEntities = bIterateEntities;
}
void SetPassEntity1( CEntityInstance* pEntity ) { m_nEntityIdsToIgnore[0] = pEntity ? pEntity->GetRefEHandle().ToInt() : -1; }
void SetPassEntity2( CEntityInstance* pEntity ) { m_nEntityIdsToIgnore[1] = pEntity ? pEntity->GetRefEHandle().ToInt() : -1; }
void SetPassEntityOwner1( CEntityInstance* pOwner ) { m_nOwnerIdsToIgnore[0] = pOwner ? pOwner->GetRefEHandle().ToInt() : -1; }
void SetPassEntityOwner2( CEntityInstance* pOwner ) { m_nOwnerIdsToIgnore[1] = pOwner ? pOwner->GetRefEHandle().ToInt() : -1; }
virtual ~CTraceFilter() {}
virtual bool ShouldHitEntity( CEntityInstance* pEntity ) { return true; }
public:
bool m_bIterateEntities; // if true then calls ShouldHitEntity for each hit entity
};
struct RnCollisionAttr_t
{
public:
RnCollisionAttr_t()
{
m_nInteractsAs = 0;
m_nInteractsWith = 0;
m_nInteractsExclude = 0;
m_nEntityId = 0;
m_nOwnerId = -1;
m_nHierarchyId = 0;
m_nCollisionGroup = COLLISION_GROUP_ALWAYS;
m_nCollisionFunctionMask = FCOLLISION_FUNC_DEFAULT;
}
bool IsSolidContactEnabled() const { return ( m_nCollisionFunctionMask & FCOLLISION_FUNC_ENABLE_SOLID_CONTACT ) != 0; }
bool IsTraceAndQueryEnabled() const { return ( m_nCollisionFunctionMask & FCOLLISION_FUNC_ENABLE_TRACE_QUERY ) != 0; }
bool IsTouchEventEnabled() const { return ( m_nCollisionFunctionMask & FCOLLISION_FUNC_ENABLE_TOUCH_EVENT ) != 0; }
bool IsSelfCollisionsEnabled() const { return ( m_nCollisionFunctionMask & FCOLLISION_FUNC_ENABLE_SELF_COLLISIONS ) != 0; }
bool ShouldIgnoreForHitboxTest() const { return ( m_nCollisionFunctionMask & FCOLLISION_FUNC_IGNORE_FOR_HITBOX_TEST ) != 0; }
bool IsTouchPersistsEnabled() const { return ( m_nCollisionFunctionMask & FCOLLISION_FUNC_ENABLE_TOUCH_PERSISTS ) != 0; }
bool HasInteractsAsLayer( int nLayerIndex ) const { return ( m_nInteractsAs & ( 1ull << nLayerIndex ) ) != 0; }
bool HasInteractsWithLayer( int nLayerIndex ) const { return ( m_nInteractsWith & ( 1ull << nLayerIndex ) ) != 0; }
bool HasInteractsExcludeLayer( int nLayerIndex ) const { return ( m_nInteractsExclude & ( 1ull << nLayerIndex ) ) != 0; }
void EnableInteractsAsLayer( int nLayer ) { m_nInteractsAs |= ( 1ull << nLayer ); }
void EnableInteractsWithLayer( int nLayer ) { m_nInteractsWith |= ( 1ull << nLayer ); }
void EnableInteractsExcludeLayer( int nLayer ) { m_nInteractsExclude |= ( 1ull << nLayer ); }
void DisableInteractsAsLayer( int nLayer ) { m_nInteractsAs &= ~( 1ull << nLayer ); }
void DisableInteractsWithLayer( int nLayer ) { m_nInteractsWith &= ~( 1ull << nLayer ); }
void DisableInteractsExcludeLayer( int nLayer ) { m_nInteractsExclude &= ~( 1ull << nLayer ); }
public:
// Which interaction layers do I represent? (e.g. I am a LAYER_INDEX_CONTENTS_PLAYER_CLIP volume)
// NOTE: This is analogous to "contents" in source 1 (bit mask of CONTENTS_* or 1<<LAYER_INDEX_*)
uint64 m_nInteractsAs;
// Which interaction layers do I interact or collide with? (e.g. I collide with LAYER_INDEX_CONTENTS_PASS_BULLETS because I am not a bullet)
// NOTE: This is analogous to the "solid mask" or "trace mask" in source 1 (bit mask of CONTENTS_* or 1<<LAYER_INDEX_*)
uint64 m_nInteractsWith;
// Which interaction layers do I _not_ interact or collide with? If my exclusion layers match m_nInteractsAs on the other object then no interaction happens.
uint64 m_nInteractsExclude;
uint32 m_nEntityId; // this is the ID of the game entity
uint32 m_nOwnerId; // this is the ID of the owner of the game entity
uint16 m_nHierarchyId; // this is an ID for the hierarchy of game entities (used to disable collision among objects in a hierarchy)
uint8 m_nCollisionGroup; // one of the registered collision groups
uint8 m_nCollisionFunctionMask; // set of CollisionFunctionMask_t bits
};
class CGameTrace
{
public:
CGameTrace()
{
Init();
}
void Init()
{
m_pSurfaceProperties = NULL;
m_pEnt = NULL;
m_pHitbox = NULL;
m_hBody = NULL;
m_hShape = NULL;
m_nContents = 0;
m_BodyTransform.SetToIdentity();
m_vHitNormal.Init();
m_vHitPoint.Init();
m_flHitOffset = 0.0f;
m_flFraction = 1.0f;
m_nTriangle = -1;
m_nHitboxBoneIndex = -1;
m_eRayType = RAY_TYPE_LINE;
m_bStartInSolid = false;
m_bExactHitPoint = false;
}
// Returns true if there was any kind of impact at all
bool DidHit() const
{
return m_flFraction < 1 || m_bStartInSolid;
}
public:
const CPhysSurfaceProperties *m_pSurfaceProperties;
CEntityInstance *m_pEnt;
const CHitBox *m_pHitbox;
HPhysicsBody m_hBody;
HPhysicsShape m_hShape;
uint64 m_nContents; // contents on other side of surface hit
CTransform m_BodyTransform;
RnCollisionAttr_t m_ShapeAttributes;
Vector m_vStartPos; // start position
Vector m_vEndPos; // final position
Vector m_vHitNormal; // surface normal at impact
Vector m_vHitPoint; // exact hit point if m_bExactHitPoint is true, otherwise equal to m_vEndPos
float m_flHitOffset; // surface normal hit offset
float m_flFraction; // time completed, 1.0 = didn't hit anything
int32 m_nTriangle; // the index of the triangle that was hit
int16 m_nHitboxBoneIndex; // the index of the hitbox bone that was hit
RayType_t m_eRayType;
bool m_bStartInSolid; // if true, the initial point was in a solid area
bool m_bExactHitPoint; // if true, then m_vHitPoint is the exact hit point of the query and the shape
private:
// No copy constructors allowed
CGameTrace(const CGameTrace& vOther);
};
//-----------------------------------------------------------------------------
// Returns true if there was any kind of impact at all
//-----------------------------------------------------------------------------
inline bool CGameTrace::DidHit() const
{
return fraction < 1 || allsolid || startsolid;
}
typedef CGameTrace trace_t;
//=============================================================================

View File

@ -0,0 +1,50 @@
#ifndef TRANSFORM_H
#define TRANSFORM_H
#ifdef _WIN32
#pragma once
#endif
#include "mathlib/vector.h"
#include "mathlib/mathlib.h"
class ALIGN16 CTransform
{
public:
CTransform() {}
CTransform( const Vector &v, const Quaternion &q ) : m_vPosition(v), m_orientation(q) {}
bool IsValid() const
{
return m_vPosition.IsValid() && m_orientation.IsValid();
}
bool operator==(const CTransform& v) const;
bool operator!=(const CTransform& v) const;
void SetToIdentity();
public:
VectorAligned m_vPosition;
QuaternionAligned m_orientation;
} ALIGN16_POST;
inline void CTransform::SetToIdentity()
{
m_vPosition = vec3_origin;
m_vPosition.w = 1.0f;
m_orientation = quat_identity;
}
inline bool CTransform::operator==(const CTransform& t) const
{
return t.m_vPosition == m_vPosition && t.m_orientation == m_orientation;
}
inline bool CTransform::operator!=(const CTransform& t) const
{
return t.m_vPosition != m_vPosition || t.m_orientation != m_orientation;
}
#endif // TRANSFORM_H