//----------------------------------------------------------------------------- // 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 }
//----------------------------------------------------------------------------- // Purpose: Checks collisions against other entities //----------------------------------------------------------------------------- void CTFFlameEntity::CheckCollision( CBaseEntity *pOther, bool *pbHitWorld ) { *pbHitWorld = false; // if we've already burnt this entity, don't do more damage, so skip even checking for collision with the entity int iIndex = m_hEntitiesBurnt.Find( pOther ); if ( iIndex != m_hEntitiesBurnt.InvalidIndex() ) return; // Do a bounding box check against the entity Vector vecMins, vecMaxs; pOther->GetCollideable()->WorldSpaceSurroundingBounds( &vecMins, &vecMaxs ); CBaseTrace trace; Ray_t ray; float flFractionLeftSolid; ray.Init( m_vecPrevPos, GetAbsOrigin(), WorldAlignMins(), WorldAlignMaxs() ); if ( IntersectRayWithBox( ray, vecMins, vecMaxs, 0.0, &trace, &flFractionLeftSolid ) ) { // if bounding box check passes, check player hitboxes trace_t trHitbox; trace_t trWorld; bool bTested = pOther->GetCollideable()->TestHitboxes( ray, MASK_SOLID | CONTENTS_HITBOX, trHitbox ); if ( !bTested || !trHitbox.DidHit() ) return; // now, let's see if the flame visual could have actually hit this player. Trace backward from the // point of impact to where the flame was fired, see if we hit anything. Since the point of impact was // determined using the flame's bounding box and we're just doing a ray test here, we extend the // start point out by the radius of the box. Vector vDir = ray.m_Delta; vDir.NormalizeInPlace(); UTIL_TraceLine( GetAbsOrigin() + vDir * WorldAlignMaxs().x, m_vecInitialPos, MASK_SOLID, this, COLLISION_GROUP_DEBRIS, &trWorld ); if ( tf_debug_flamethrower.GetInt() ) { NDebugOverlay::Line( trWorld.startpos, trWorld.endpos, 0, 255, 0, true, 3.0f ); } if ( trWorld.fraction == 1.0 ) { // if there is nothing solid in the way, damage the entity OnCollide( pOther ); } else { // we hit the world, remove ourselves *pbHitWorld = true; UTIL_Remove( this ); } } }
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 ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CEditorSystem::DoSelect( CHL2WarsPlayer *pPlayer ) { #ifndef CLIENT_DLL // Sync from client return; #endif // CLIENT_DLL Vector vPos = pPlayer->Weapon_ShootPosition(); const Vector &vMouseAim = pPlayer->GetMouseAim(); const Vector &vCamOffset = pPlayer->GetCameraOffset(); Vector vStartPos, vEndPos; vStartPos = vPos + vCamOffset; vEndPos = vStartPos + (vMouseAim * MAX_TRACE_LENGTH); //NDebugOverlay::Line( vStartPos, vEndPos, 0, 255, 0, true, 4.0f ); Ray_t pickerRay; pickerRay.Init( vStartPos, vEndPos ); CWarsFlora *pBest = NULL; float fBestDistance = 0; #ifdef CLIENT_DLL for( CBaseEntity *pEntity = ClientEntityList().FirstBaseEntity(); pEntity; pEntity = ClientEntityList().NextBaseEntity( pEntity ) ) #else for( CBaseEntity *pEntity = gEntList.FirstEnt(); pEntity != NULL; pEntity = gEntList.NextEnt( pEntity ) ) #endif // CLIENT_DLL { CWarsFlora *pFlora = dynamic_cast<CWarsFlora *>( pEntity ); if( pFlora ) { // Prefer testing against hitboxes // If no hitboxes available, use the bounding box trace_t trace; bool bTestedHitBoxes = pFlora->TestHitboxes( pickerRay, MASK_SOLID, trace ); if( bTestedHitBoxes ) { if( trace.DidHit() ) { float fDistance = trace.endpos.DistTo( vStartPos ); if( !pBest || fDistance < fBestDistance ) { pBest = pFlora; fBestDistance = fDistance; } } } else { CBaseTrace trace2; if ( IntersectRayWithBox( pickerRay, pFlora->GetAbsOrigin() + pFlora->CollisionProp()->OBBMins(), pFlora->GetAbsOrigin() + pFlora->CollisionProp()->OBBMaxs(), 0.5f, &trace2 ) ) { float fDistance = trace2.endpos.DistTo( vStartPos ); if( !pBest || fDistance < fBestDistance ) { pBest = pFlora; fBestDistance = fDistance; } } } } } if( pBest ) { if( !IsSelected( pBest ) ) { Select( pBest ); KeyValues *pOperation = new KeyValues( "data" ); pOperation->SetString("operation", "select"); KeyValues *pFloraKey = new KeyValues( "flora", "uuid", pBest->GetFloraUUID() ); pFloraKey->SetBool( "select", true ); pOperation->AddSubKey( pFloraKey ); warseditorstorage->QueueServerCommand( pOperation ); } else { Deselect( pBest ); KeyValues *pOperation = new KeyValues( "data" ); pOperation->SetString("operation", "select"); KeyValues *pFloraKey = new KeyValues( "flora", "uuid", pBest->GetFloraUUID() ); pFloraKey->SetBool( "select", false ); pOperation->AddSubKey( pFloraKey ); warseditorstorage->QueueServerCommand( pOperation ); } //NDebugOverlay::Box( pBest->GetAbsOrigin(), -Vector(8, 8, 8), Vector(8, 8, 8), 0, 255, 0, 255, 5.0f); } }