diff --git a/src/game/client/neo/c_neo_player.h b/src/game/client/neo/c_neo_player.h index 6330342ae..c4db72e30 100644 --- a/src/game/client/neo/c_neo_player.h +++ b/src/game/client/neo/c_neo_player.h @@ -61,6 +61,7 @@ class C_NEO_Player : public C_HL2MP_Player virtual float GetFOV( void ); virtual CStudioHdr *OnNewModel( void ); virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator ); + virtual bool TestHitboxes(const Ray_t &ray, unsigned int fContentsMask, trace_t &tr) override; virtual void ItemPreFrame( void ); virtual void ItemPostFrame( void ); virtual float GetMinFOV() const; diff --git a/src/game/server/neo/neo_player.h b/src/game/server/neo/neo_player.h index 93bd682c7..d5ac07ede 100644 --- a/src/game/server/neo/neo_player.h +++ b/src/game/server/neo/neo_player.h @@ -101,6 +101,7 @@ class CNEO_Player : public CHL2MP_Player virtual CBaseEntity* FindUseEntity() override; virtual void InitVCollision(const Vector& vecAbsOrigin, const Vector& vecAbsVelocity) OVERRIDE; + virtual bool TestHitboxes(const Ray_t &ray, unsigned int fContentsMask, trace_t &tr) override; virtual void ModifyFireBulletsDamage(CTakeDamageInfo* dmgInfo) OVERRIDE; diff --git a/src/game/shared/neo/neo_player_shared.cpp b/src/game/shared/neo/neo_player_shared.cpp index de7b404d3..dcbdd8887 100644 --- a/src/game/shared/neo/neo_player_shared.cpp +++ b/src/game/shared/neo/neo_player_shared.cpp @@ -16,6 +16,7 @@ #include "c_neo_player.h" #include "c_playerresource.h" #include "ui/neo_hud_context_hint.h" +#include "vprof.h" #define CNEO_Player C_NEO_Player #else #include "neo_player.h" @@ -42,6 +43,8 @@ #include "c_te_effect_dispatch.h" #endif // GAME_DLL +#include "bone_setup.h" + // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -707,4 +710,90 @@ CBaseEntity *CNEO_Player::FindUseEntity() } return pNearest; +} + +bool CNEO_Player::TestHitboxes(const Ray_t& ray, unsigned int fContentsMask, trace_t& tr) +{ +#ifdef CLIENT_DLL + VPROF( "C_BaseAnimating::TestHitboxes" ); + + MDLCACHE_CRITICAL_SECTION(); +#endif // CLIENT_DLL + + CStudioHdr *pStudioHdr = GetModelPtr(); + if (!pStudioHdr) + return false; + + mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( m_nHitboxSet ); + if ( !set || !set->numhitboxes ) + return false; + + // Use vcollide for box traces. + if ( !ray.m_IsRay ) + return false; + + // This *has* to be true for the existing code to function correctly. + Assert( ray.m_StartOffset == vec3_origin ); + +#ifdef GAME_DLL + CBoneCache *pCache = GetBoneCache( ); +#else + CBoneCache *pCache = GetBoneCache( pStudioHdr ); +#endif // GAME_DLL + matrix3x4_t *hitboxbones[MAXSTUDIOBONES]; + pCache->ReadCachedBonePointers( hitboxbones, pStudioHdr->numbones() ); + +#ifdef GAME_DLL + if ( TraceToStudio( physprops, ray, pStudioHdr, set, hitboxbones, fContentsMask, GetAbsOrigin(), GetModelScale(), tr ) ) +#else + if ( TraceToStudio( physprops, ray, pStudioHdr, set, hitboxbones, fContentsMask, GetRenderOrigin(), GetModelScale(), tr ) ) +#endif // GAME_DLL + { + mstudiobbox_t *pbox = set->pHitbox( tr.hitbox ); + mstudiobone_t *pBone = pStudioHdr->pBone(pbox->bone); + tr.surface.name = "**studio**"; + tr.surface.flags = SURF_HITBOX; + tr.surface.surfaceProps = physprops->GetSurfaceIndex( pBone->pszSurfaceProp() ); + + if (fContentsMask & CONTENTS_HITBOX) + { + switch (tr.hitgroup) + { + case HITGROUP_LEFTARM: + case HITGROUP_RIGHTARM: + case HITGROUP_LEFTLEG: + case HITGROUP_RIGHTLEG: + case HITGROUP_GEAR: + trace_t secondTrace; + unsigned int fHitboxGroupMask = UINT_MAX; + fHitboxGroupMask = fHitboxGroupMask & ~(1 << HITGROUP_LEFTARM); + fHitboxGroupMask = fHitboxGroupMask & ~(1 << HITGROUP_RIGHTARM); + fHitboxGroupMask = fHitboxGroupMask & ~(1 << HITGROUP_LEFTLEG); + fHitboxGroupMask = fHitboxGroupMask & ~(1 << HITGROUP_RIGHTLEG); + fHitboxGroupMask = fHitboxGroupMask & ~(1 << HITGROUP_GEAR); + #ifdef GAME_DLL + if (TraceToStudio(physprops, ray, pStudioHdr, set, hitboxbones, fContentsMask, GetAbsOrigin(), GetModelScale(), secondTrace, fHitboxGroupMask)) + #else + if (TraceToStudio(physprops, ray, pStudioHdr, set, hitboxbones, fContentsMask, GetRenderOrigin(), GetModelScale(), secondTrace, fHitboxGroupMask)) + #endif // GAME_DLL + { + tr.hitgroup = secondTrace.hitgroup; + } + } + } + +#ifdef CLIENT_DLL + if ( IsRagdoll() ) + { + IPhysicsObject *pReplace = m_pRagdoll->GetElement( tr.physicsbone ); + if ( pReplace ) + { + VPhysicsSetObject( NULL ); + VPhysicsSetObject( pReplace ); + } + } +#endif // CLIENT_DLL + } + + return true; } \ No newline at end of file diff --git a/src/public/bone_setup.cpp b/src/public/bone_setup.cpp index 61fa5dda7..f214e6192 100644 --- a/src/public/bone_setup.cpp +++ b/src/public/bone_setup.cpp @@ -5380,8 +5380,12 @@ bool SweepBoxToStudio( IPhysicsSurfaceProps *pProps, const Ray_t& ray, CStudioHd //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -bool TraceToStudio( IPhysicsSurfaceProps *pProps, const Ray_t& ray, CStudioHdr *pStudioHdr, mstudiohitboxset_t *set, +bool TraceToStudio( IPhysicsSurfaceProps *pProps, const Ray_t& ray, CStudioHdr *pStudioHdr, mstudiohitboxset_t *set, +#ifdef NEO + matrix3x4_t **hitboxbones, int fContentsMask, const Vector &vecOrigin, float flScale, trace_t &tr, unsigned int fHitboxGroupMask ) +#else matrix3x4_t **hitboxbones, int fContentsMask, const Vector &vecOrigin, float flScale, trace_t &tr ) +#endif // NEO { if ( !ray.m_IsRay ) { @@ -5400,6 +5404,11 @@ bool TraceToStudio( IPhysicsSurfaceProps *pProps, const Ray_t& ray, CStudioHdr * { mstudiobbox_t *pbox = set->pHitbox(i); +#ifdef NEO + if ((fHitboxGroupMask & (1 << pbox->group)) == 0) + continue; +#endif // NEO + // Filter based on contents mask int fBoneContents = pStudioHdr->pBone( pbox->bone )->contents; if ( ( fBoneContents & fContentsMask ) == 0 ) diff --git a/src/public/bone_setup.h b/src/public/bone_setup.h index 9a3d6ec00..7c6977242 100644 --- a/src/public/bone_setup.h +++ b/src/public/bone_setup.h @@ -462,7 +462,11 @@ void Studio_DestroyBoneCache( memhandle_t cacheHandle ); void Studio_InvalidateBoneCache( memhandle_t cacheHandle ); // Given a ray, trace for an intersection with this studiomodel. Get the array of bones from StudioSetupHitboxBones +#ifdef NEO +bool TraceToStudio( class IPhysicsSurfaceProps *pProps, const Ray_t& ray, CStudioHdr *pStudioHdr, mstudiohitboxset_t *set, matrix3x4_t **hitboxbones, int fContentsMask, const Vector &vecOrigin, float flScale, trace_t &trace, unsigned int fHitboxGroupMask = UINT_MAX ); +#else bool TraceToStudio( class IPhysicsSurfaceProps *pProps, const Ray_t& ray, CStudioHdr *pStudioHdr, mstudiohitboxset_t *set, matrix3x4_t **hitboxbones, int fContentsMask, const Vector &vecOrigin, float flScale, trace_t &trace ); +#endif // NEO void QuaternionSM( float s, const Quaternion &p, const Quaternion &q, Quaternion &qt ); void QuaternionMA( const Quaternion &p, float s, const Quaternion &q, Quaternion &qt );