namespace mbed_cellular_trace { typedef struct trace_s { void (*mutex_wait_f)(void); void (*mutex_release_f)(void); } trace_t; static trace_t m_trace = {}; void mutex_wait_function_set(void (*mutex_wait_f)(void)) { m_trace.mutex_wait_f = mutex_wait_f; } void mutex_release_function_set(void (*mutex_release_f)(void)) { m_trace.mutex_release_f = mutex_release_f; } void mutex_wait() { if (m_trace.mutex_wait_f) { m_trace.mutex_wait_f(); } } void mutex_release() { if (m_trace.mutex_release_f) { m_trace.mutex_release_f(); } } } // namespace mbed_cellular_trace
//----------------------------------------------------------------------------- // Purpose: Do not test against hit boxes, but against the bounding box. // Much cheaper and we don't really need hitboxes for hl2wars. //----------------------------------------------------------------------------- bool CUnitBase::TestHitboxes( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr ) { #if 1 if( unit_cheaphitboxtest.GetBool() == false ) return BaseClass::TestHitboxes( ray, fContentsMask, tr ); CStudioHdr *pStudioHdr = GetModelPtr( ); if (!pStudioHdr) return false; Ray_t ray2 = ray; Vector start = GetAbsOrigin() - ray.m_Start; ray2.Init(start, start+ray.m_Delta); IntersectRayWithBox(ray2, WorldAlignMins(), WorldAlignMaxs(), 0.0f, &tr); if ( tr.DidHit() ) { tr.surface.name = "**studio**"; tr.surface.flags = SURF_HITBOX; tr.surface.surfaceProps = VPhysicsGetObject() ? VPhysicsGetObject()->GetMaterialIndex() : 0; //NDebugOverlay::SweptBox(ray.m_Start, tr.endpos, -Vector(32, 32, 32), Vector(32, 32, 32), GetAbsAngles(), 255, 0, 0, 255, 1.0f); return true; } return false; #else return BaseClass::TestHitboxes( ray, fContentsMask, tr ); #endif // 0 }
bool CStatueProp::TestCollision( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr ) { IPhysicsObject *pPhysObject = VPhysicsGetObject(); if ( pPhysObject ) { Vector vecPosition; QAngle vecAngles; pPhysObject->GetPosition( &vecPosition, &vecAngles ); const CPhysCollide *pScaledCollide = pPhysObject->GetCollide(); physcollision->TraceBox( ray, pScaledCollide, vecPosition, vecAngles, &tr ); return tr.DidHit(); } return false; }
//----------------------------------------------------------------------------- // Purpose: Play a sound for an impact. If tr contains a valid hit, use that. // If not, use the passed in origin & surface. //----------------------------------------------------------------------------- void PlayImpactSound( CBaseEntity *pEntity, trace_t &tr, Vector &vecServerOrigin, int nServerSurfaceProp ) { VPROF( "PlayImpactSound" ); surfacedata_t *pdata; Vector vecOrigin; // If the client-side trace hit a different entity than the server, or // the server didn't specify a surfaceprop, then use the client-side trace // material if it's valid. if ( tr.DidHit() && (pEntity != tr.m_pEnt || nServerSurfaceProp == 0) ) { nServerSurfaceProp = tr.surface.surfaceProps; } pdata = physprops->GetSurfaceData( nServerSurfaceProp ); if ( tr.fraction < 1.0 ) { vecOrigin = tr.endpos; } else { vecOrigin = vecServerOrigin; } // Now play the esound if ( pdata->sounds.bulletImpact ) { const char *pbulletImpactSoundName = physprops->GetString( pdata->sounds.bulletImpact ); if ( g_pImpactSoundRouteFn ) { g_pImpactSoundRouteFn( pbulletImpactSoundName, vecOrigin ); } else { CLocalPlayerFilter filter; C_BaseEntity::EmitSound( filter, NULL, pbulletImpactSoundName, pdata->soundhandles.bulletImpact, &vecOrigin ); } return; } #ifdef _DEBUG Msg("***ERROR: PlayImpactSound() on a surface with 0 bulletImpactCount!\n"); #endif //_DEBUG }
bool C_BasePropDoor::TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace ) { if ( !VPhysicsGetObject() ) return false; CStudioHdr *pStudioHdr = GetModelPtr( ); if (!pStudioHdr) return false; physcollision->TraceBox( ray, VPhysicsGetObject()->GetCollide(), GetAbsOrigin(), GetAbsAngles(), &trace ); if ( trace.DidHit() ) { trace.surface.surfaceProps = VPhysicsGetObject()->GetMaterialIndex(); return true; } return false; }
//----------------------------------------------------------------------------- // Implement this if you want to know when the player collides during OnPlayerMove //----------------------------------------------------------------------------- void CTFGameMovementRecon::OnTryPlayerMoveCollision( trace_t &tr ) { if ( !m_bPerformingAirMove ) return; // Only keep track of world collisions if ( tr.DidHitWorld() ) { CTFMoveData *pTFMove = TFMove(); if ( pTFMove ) { if ( ( pTFMove->ReconData().m_flSuppressionJumpTime == TIME_WALL_INVALID ) && ( pTFMove->ReconData().m_flSuppressionImpactTime == TIME_WALL_INVALID ) ) { // No walljumps off of mostly horizontal surfaces... if ( fabs( tr.plane.normal.z ) > 0.9f ) return; // No walljumps off of the same plane as the last one... if ( (pTFMove->ReconData().m_flImpactDist == tr.plane.dist) && (VectorsAreEqual(pTFMove->ReconData().m_vecImpactNormal, tr.plane.normal, 1e-2) ) ) { return; } // If you hit a wall, no double jumps for you pTFMove->ReconData().m_nJumpCount = 2; // Play an impact sound MoveHelper()->StartSound( pTFMove->m_vecAbsOrigin, "Recon.WallJump" ); pTFMove->ReconData().m_vecImpactNormal = tr.plane.normal; pTFMove->ReconData().m_flImpactDist = tr.plane.dist; pTFMove->ReconData().m_flActiveJumpTime = TIME_WALL_ACTIVATE_JUMP; pTFMove->ReconData().m_flSuppressionImpactTime = TIME_WALL_SUPPRESSION_IMPACT; } } } }
float CWeaponPortalgun::TraceFirePortal( bool bPortal2, const Vector &vTraceStart, const Vector &vDirection, trace_t &tr, Vector &vFinalPosition, QAngle &qFinalAngles, int iPlacedBy, bool bTest /*= false*/ ) { CTraceFilterSimpleClassnameList baseFilter( this, COLLISION_GROUP_NONE ); UTIL_Portal_Trace_Filter( &baseFilter ); CTraceFilterTranslateClones traceFilterPortalShot( &baseFilter ); Ray_t rayEyeArea; rayEyeArea.Init( vTraceStart + vDirection * 24.0f, vTraceStart + vDirection * -24.0f ); float fMustBeCloserThan = 2.0f; CProp_Portal *pNearPortal = UTIL_Portal_FirstAlongRay( rayEyeArea, fMustBeCloserThan ); if ( !pNearPortal ) { // Check for portal near and infront of you rayEyeArea.Init( vTraceStart + vDirection * -24.0f, vTraceStart + vDirection * 48.0f ); fMustBeCloserThan = 2.0f; pNearPortal = UTIL_Portal_FirstAlongRay( rayEyeArea, fMustBeCloserThan ); } if ( pNearPortal && pNearPortal->IsActivedAndLinked() ) { iPlacedBy = PORTAL_PLACED_BY_PEDESTAL; Vector vPortalForward; pNearPortal->GetVectors( &vPortalForward, 0, 0 ); if ( vDirection.Dot( vPortalForward ) < 0.01f ) { // If shooting out of the world, fizzle if ( !bTest ) { CProp_Portal *pPortal = CProp_Portal::FindPortal( m_iPortalLinkageGroupID, bPortal2, true ); pPortal->m_iDelayedFailure = ( ( pNearPortal->m_bIsPortal2 ) ? ( PORTAL_FIZZLE_NEAR_RED ) : ( PORTAL_FIZZLE_NEAR_BLUE ) ); VectorAngles( vPortalForward, pPortal->m_qDelayedAngles ); pPortal->m_vDelayedPosition = pNearPortal->GetAbsOrigin(); vFinalPosition = pPortal->m_vDelayedPosition; qFinalAngles = pPortal->m_qDelayedAngles; UTIL_TraceLine( vTraceStart - vDirection * 16.0f, vTraceStart + (vDirection * m_fMaxRange1), MASK_SHOT_PORTAL, &traceFilterPortalShot, &tr ); return PORTAL_ANALOG_SUCCESS_NEAR; } UTIL_TraceLine( vTraceStart - vDirection * 16.0f, vTraceStart + (vDirection * m_fMaxRange1), MASK_SHOT_PORTAL, &traceFilterPortalShot, &tr ); return PORTAL_ANALOG_SUCCESS_OVERLAP_LINKED; } } // Trace to see where the portal hit UTIL_TraceLine( vTraceStart, vTraceStart + (vDirection * m_fMaxRange1), MASK_SHOT_PORTAL, &traceFilterPortalShot, &tr ); if ( !tr.DidHit() || tr.startsolid ) { // If it didn't hit anything, fizzle if ( !bTest ) { CProp_Portal *pPortal = CProp_Portal::FindPortal( m_iPortalLinkageGroupID, bPortal2, true ); pPortal->m_iDelayedFailure = PORTAL_FIZZLE_NONE; VectorAngles( -vDirection, pPortal->m_qDelayedAngles ); pPortal->m_vDelayedPosition = tr.endpos; vFinalPosition = pPortal->m_vDelayedPosition; qFinalAngles = pPortal->m_qDelayedAngles; } return PORTAL_ANALOG_SUCCESS_PASSTHROUGH_SURFACE; } // Trace to the surface to see if there's a rotating door in the way CBaseEntity *list[1024]; Ray_t ray; ray.Init( vTraceStart, tr.endpos ); int nCount = UTIL_EntitiesAlongRay( list, 1024, ray, 0 ); // Loop through all entities along the ray between the gun and the surface for ( int i = 0; i < nCount; i++ ) { // If the entity is a rotating door if( FClassnameIs( list[i], "prop_door_rotating" ) ) { // Check more precise door collision CBasePropDoor *pRotatingDoor = static_cast<CBasePropDoor *>( list[i] ); Ray_t rayDoor; rayDoor.Init( vTraceStart, vTraceStart + (vDirection * m_fMaxRange1) ); trace_t trDoor; pRotatingDoor->TestCollision( rayDoor, 0, trDoor ); if ( trDoor.DidHit() ) { // There's a door in the way tr = trDoor; if ( sv_portal_placement_debug.GetBool() ) { Vector vMin; Vector vMax; Vector vZero = Vector( 0.0f, 0.0f, 0.0f ); list[ i ]->GetCollideable()->WorldSpaceSurroundingBounds( &vMin, &vMax ); NDebugOverlay::Box( vZero, vMin, vMax, 0, 255, 0, 128, 0.5f ); } if ( !bTest ) { CProp_Portal *pPortal = CProp_Portal::FindPortal( m_iPortalLinkageGroupID, bPortal2, true ); pPortal->m_iDelayedFailure = PORTAL_FIZZLE_CANT_FIT; VectorAngles( tr.plane.normal, pPortal->m_qDelayedAngles ); pPortal->m_vDelayedPosition = trDoor.endpos; vFinalPosition = pPortal->m_vDelayedPosition; qFinalAngles = pPortal->m_qDelayedAngles; } return PORTAL_ANALOG_SUCCESS_CANT_FIT; } } else if ( FClassnameIs( list[i], "trigger_portal_cleanser" ) ) { CBaseTrigger *pTrigger = static_cast<CBaseTrigger*>( list[i] ); if ( pTrigger && !pTrigger->m_bDisabled ) { Vector vMin; Vector vMax; pTrigger->GetCollideable()->WorldSpaceSurroundingBounds( &vMin, &vMax ); IntersectRayWithBox( ray.m_Start, ray.m_Delta, vMin, vMax, 0.0f, &tr ); tr.plane.normal = -vDirection; if ( !bTest ) { CProp_Portal *pPortal = CProp_Portal::FindPortal( m_iPortalLinkageGroupID, bPortal2, true ); pPortal->m_iDelayedFailure = PORTAL_FIZZLE_CLEANSER; VectorAngles( tr.plane.normal, pPortal->m_qDelayedAngles ); pPortal->m_vDelayedPosition = tr.endpos; vFinalPosition = pPortal->m_vDelayedPosition; qFinalAngles = pPortal->m_qDelayedAngles; } return PORTAL_ANALOG_SUCCESS_CLEANSER; } } } Vector vUp( 0.0f, 0.0f, 1.0f ); if( ( tr.plane.normal.x > -0.001f && tr.plane.normal.x < 0.001f ) && ( tr.plane.normal.y > -0.001f && tr.plane.normal.y < 0.001f ) ) { //plane is a level floor/ceiling vUp = vDirection; } // Check that the placement succeed VectorAngles( tr.plane.normal, vUp, qFinalAngles ); vFinalPosition = tr.endpos; return VerifyPortalPlacement( CProp_Portal::FindPortal( m_iPortalLinkageGroupID, bPortal2 ), vFinalPosition, qFinalAngles, iPlacedBy, bTest ); }
//Called from PhysicsSimulate() or ReceiveMessage() bool CDHLProjectile::OnTouch( trace_t &touchtr, bool bDecalOnly /*= false*/, ITraceFilter* pTraceFilter /*= NULL*/ ) { //Direction Vector vecDir = touchtr.endpos - touchtr.startpos; if ( vecDir == vec3_origin ) //Sometimes endpos==startpos so we need to get dir from velocity instead { #ifdef CLIENT_DLL vecDir = GetLocalVelocity(); #else vecDir = m_vecCurVelocity; #endif VectorNormalize( vecDir ); } CBaseEntity* ent = touchtr.m_pEnt; if ( !ent ) return false; if ( touchtr.DidHit() ) { //Never collide with self, shooter, or other projectiles if ( ent == this || dynamic_cast<CDHLProjectile*>(ent) || ent == (CBaseEntity*)m_pShooter ) //|| ( (m_iType == DHL_PROJECTILE_TYPE_COMBATKNIFE) && (ent == m_pFiringWeapon) ) ) //Combat knife - don't collide with weapon ent return false; //Hack: Sometimes hits are registered prematurely (usually to the torso area) with no hitbox. Pretend nothing happened unless one is found. if ( ent->IsPlayer() && touchtr.hitgroup == 0 ) return false; //Check friendly fire if ( CheckFriendlyFire( ent ) ) { if ( !bDecalOnly ) { ClearMultiDamage(); //Do damage CTakeDamageInfo dmgInfo( this, GetOwnerEntity(), m_iDamage, DMG_BULLET ); if ( m_iType == DHL_PROJECTILE_TYPE_COMBATKNIFE ) { //CalculateMeleeDamageForce( &dmgInfo, vecDir, touchtr.endpos, 0.01f ); Vector vecForce = vecDir; VectorNormalize( vecForce ); //vecForce *= 10.0f; //Ripped from C_ClientRagdoll::ImpactTrace dmgInfo.SetDamageForce( vecForce ); #ifndef CLIENT_DLL if ( IsOnFire() ) { CBaseAnimating* pBAnim = dynamic_cast<CBaseAnimating*>(ent); if ( pBAnim ) pBAnim->Ignite( 10.0f, false ); } #endif } else CalculateBulletDamageForce( &dmgInfo, m_iAmmoType, vecDir, touchtr.endpos, 1.0f ); dmgInfo.SetDamagePosition( touchtr.endpos ); ent->DispatchTraceAttack( dmgInfo, vecDir, &touchtr ); ApplyMultiDamage(); } #ifdef CLIENT_DLL if ( ent->GetCollisionGroup() == COLLISION_GROUP_BREAKABLE_GLASS ) return false; //Decals and such if ( !( touchtr.surface.flags & SURF_SKY ) && !touchtr.allsolid ) { IPredictionSystem::SuppressEvents( false ); if ( (m_iType == DHL_PROJECTILE_TYPE_BULLET || m_iType == DHL_PROJECTILE_TYPE_PELLET) ) { UTIL_ImpactTrace( &touchtr, DMG_BULLET ); } if ( m_iType == DHL_PROJECTILE_TYPE_COMBATKNIFE ) PlayImpactSound( touchtr.m_pEnt, touchtr, touchtr.endpos, touchtr.surface.surfaceProps ); IPredictionSystem::SuppressEvents( !prediction->IsFirstTimePredicted() ); } #endif } if ( pTraceFilter && m_iType != DHL_PROJECTILE_TYPE_COMBATKNIFE ) { PenetrationData_t nPenetrationData = DHLShared::TestPenetration( touchtr, m_pShooter, pTraceFilter, m_iTimesPenetrated, m_flDistanceTravelled, m_iAmmoType ); if ( nPenetrationData.m_bShouldPenetrate ) { m_flDistanceTravelled += GetLocalOrigin().DistTo( nPenetrationData.m_vecNewBulletPos ); MoveProjectileToPosition( nPenetrationData.m_vecNewBulletPos ); m_iTimesPenetrated++; return true; //Keep going - but don't do anything else in this frame of PhysicsSimulate() } } //We're done unless what we hit was breakable glass if ( ent->GetCollisionGroup() != COLLISION_GROUP_BREAKABLE_GLASS ) { #ifdef CLIENT_DLL m_bCollided = true; AddEffects( EF_NODRAW ); if ( m_pTrail ) //NULL pointer here sometimes somehow... m_pTrail->AddEffects( EF_NODRAW ); #else EntityMessageBegin( this ); WRITE_BYTE( MSG_NOTIFY_REMOVAL ); MessageEnd(); if ( touchtr.DidHitWorld() && m_iType == DHL_PROJECTILE_TYPE_COMBATKNIFE && !( touchtr.surface.flags & SURF_SKY ) ) { CBaseCombatWeapon* pKnifeEnt = assert_cast<CBaseCombatWeapon*>(CreateEntityByName( "weapon_combatknife" )); if ( pKnifeEnt ) { pKnifeEnt->AddSpawnFlags( SF_NORESPAWN ); //Needed for weapon spawn & VPhysics setup to work correctly pKnifeEnt->SetAbsOrigin( touchtr.endpos ); QAngle angles = vec3_angle; Vector vecKnifeDir = touchtr.startpos - touchtr.endpos; VectorAngles( vecKnifeDir, angles ); angles[PITCH] -= 15.0f; //Correct for the .mdl being offset a bit pKnifeEnt->SetLocalAngles( angles ); DispatchSpawn( pKnifeEnt ); //Spawns vphys object and sets it up, essentially a copy of CWeaponHL2MPBase::FallInit() pKnifeEnt->VPhysicsDestroyObject(); //Using SOLID_VPHYSICS instead of SOLID_BBOX (as ordinary weapons do) helps resolve some of the client side collision oddities Assert( pKnifeEnt->VPhysicsInitNormal( SOLID_VPHYSICS, FSOLID_NOT_STANDABLE | FSOLID_TRIGGER, true ) ); pKnifeEnt->SetPickupTouch(); //Sets up automagic removal after time IPhysicsObject* pKnifePhys = pKnifeEnt->VPhysicsGetObject(); if ( pKnifePhys ) { //Knives are solid to bullets...the only way to make them non-solid to bullets is to do SetSolid( SOLID_NONE ) or AddSolidFlags( FSOLID_NOT_SOLID ) //which breaks the +use pickup even with FSOLID_TRIGGER set. Let's just call it a feature :) pKnifePhys->EnableMotion( false ); pKnifePhys->EnableCollisions( false ); } if ( IsOnFire() ) pKnifeEnt->Ignite( 10.0f, false ); } } //SetThink( &CDHLProjectile::SUB_Remove ); //SetNextThink( gpGlobals->curtime + 0.1 ); //SUB_Remove(); //SetMoveType( MOVETYPE_NONE ); m_flRemoveAt = gpGlobals->curtime + 0.1f; //Give the notification message a head start so that the client will have time to react #endif } } return true; }
void mutex_release() { if (m_trace.mutex_release_f) { m_trace.mutex_release_f(); } }
void mutex_wait() { if (m_trace.mutex_wait_f) { m_trace.mutex_wait_f(); } }