void FoundryHelpers_DrawEntityHighlightEffect( C_BaseEntity *pEnt ) { CCollisionProperty *pCollision = pEnt->CollisionProp(); // Transform the OBB corners into world space. const Vector &vMins = pCollision->OBBMins(); const Vector &vMaxs = pCollision->OBBMaxs(); Vector vPoints[8] = { Vector( vMins.x, vMins.y, vMins.z ), Vector( vMaxs.x, vMins.y, vMins.z ), Vector( vMaxs.x, vMaxs.y, vMins.z ), Vector( vMins.x, vMaxs.y, vMins.z ), Vector( vMins.x, vMins.y, vMaxs.z ), Vector( vMaxs.x, vMins.y, vMaxs.z ), Vector( vMaxs.x, vMaxs.y, vMaxs.z ), Vector( vMins.x, vMaxs.y, vMaxs.z ) }; for ( int i=0; i < 8; i++ ) { Vector vTmp; vPoints[i] = pCollision->CollisionToWorldSpace( vPoints[i], &vTmp ); } // Draw lines connecting them up... for ( int i=0; i < 4; i++ ) { AddCoolLine( vPoints[i], vPoints[(i+1)%4], 0, false ); AddCoolLine( vPoints[i+4], vPoints[(i+1)%4 + 4], 4, true ); AddCoolLine( vPoints[i], vPoints[i+4], i*2+4, (i%1) == 0 ); } }
static bool IsSmall( CBaseEntity *pBlocker ) { CCollisionProperty *pCollisionProp = pBlocker->CollisionProp(); int nSmaller = 0; Vector vecSize = pCollisionProp->OBBMaxs() - pCollisionProp->OBBMins(); for ( int i = 0; i < 3; i++ ) { if ( vecSize[i] >= 42 ) return false; if ( vecSize[i] <= 30 ) { nSmaller++; } } return ( nSmaller >= 2 ); }
//----------------------------------------------------------------------------- // Purpose: Breaks the breakable. m_hBreaker is the entity that caused us to break. //----------------------------------------------------------------------------- void CBreakable::Die( void ) { Vector vecVelocity;// shard velocity char cFlag = 0; int pitch; float fvol; pitch = 95 + random->RandomInt(0,29); if (pitch > 97 && pitch < 103) { pitch = 100; } // The more negative m_iHealth, the louder // the sound should be. fvol = random->RandomFloat(0.85, 1.0) + (abs(m_iHealth) / 100.0); if (fvol > 1.0) { fvol = 1.0; } const char *soundname = NULL; switch (m_Material) { default: break; case matGlass: soundname = "Breakable.Glass"; cFlag = BREAK_GLASS; break; case matWood: soundname = "Breakable.Crate"; cFlag = BREAK_WOOD; break; case matComputer: soundname = "Breakable.Computer"; cFlag = BREAK_METAL; break; case matMetal: soundname = "Breakable.Metal"; cFlag = BREAK_METAL; break; case matFlesh: case matWeb: soundname = "Breakable.Flesh"; cFlag = BREAK_FLESH; break; case matRocks: case matCinderBlock: soundname = "Breakable.Concrete"; cFlag = BREAK_CONCRETE; break; case matCeilingTile: soundname = "Breakable.Ceiling"; break; } if ( soundname ) { if ( m_hBreaker && m_hBreaker->IsPlayer() ) { IGameEvent * event = gameeventmanager->CreateEvent( "break_breakable" ); if ( event ) { event->SetInt( "userid", ToBasePlayer( m_hBreaker )->GetUserID() ); event->SetInt( "entindex", entindex() ); event->SetInt( "material", cFlag ); gameeventmanager->FireEvent( event ); } } CSoundParameters params; if ( GetParametersForSound( soundname, params, NULL ) ) { CPASAttenuationFilter filter( this ); EmitSound_t ep; ep.m_nChannel = params.channel; ep.m_pSoundName = params.soundname; ep.m_flVolume = fvol; ep.m_SoundLevel = params.soundlevel; ep.m_nPitch = pitch; EmitSound( filter, entindex(), ep ); } } switch( m_Explosion ) { case expDirected: vecVelocity = g_vecAttackDir * -200; break; case expUsePrecise: { AngleVectors( m_GibDir, &vecVelocity, NULL, NULL ); vecVelocity *= 200; } break; case expRandom: vecVelocity.x = 0; vecVelocity.y = 0; vecVelocity.z = 0; break; default: DevMsg("**ERROR - Unspecified gib dir method in func_breakable!\n"); break; } Vector vecSpot = WorldSpaceCenter(); CPVSFilter filter2( vecSpot ); int iModelIndex = 0; CCollisionProperty *pCollisionProp = CollisionProp(); Vector vSize = pCollisionProp->OBBSize(); int iCount = ( vSize[0] * vSize[1] + vSize[1] * vSize[2] + vSize[2] * vSize[0] ) / ( 3 * 12 * 12 ); if ( iCount > func_break_max_pieces.GetInt() ) { iCount = func_break_max_pieces.GetInt(); } ConVarRef breakable_disable_gib_limit( "breakable_disable_gib_limit" ); if ( !breakable_disable_gib_limit.GetBool() && iCount ) { if ( m_PerformanceMode == PM_NO_GIBS ) { iCount = 0; } else if ( m_PerformanceMode == PM_REDUCED_GIBS ) { int iNewCount = iCount * func_break_reduction_factor.GetFloat(); iCount = MAX( iNewCount, 1 ); } } if ( m_iszModelName != NULL_STRING ) { for ( int i = 0; i < iCount; i++ ) { #ifdef HL1_DLL // Use the passed model instead of the propdata type const char *modelName = STRING( m_iszModelName ); // if the map specifies a model by name if( strstr( modelName, ".mdl" ) != NULL ) { iModelIndex = modelinfo->GetModelIndex( modelName ); } else // do the hl2 / normal way #endif iModelIndex = modelinfo->GetModelIndex( g_PropDataSystem.GetRandomChunkModel( STRING( m_iszModelName ) ) ); // All objects except the first one in this run are marked as slaves... int slaveFlag = 0; if ( i != 0 ) { slaveFlag = BREAK_SLAVE; } te->BreakModel( filter2, 0.0, vecSpot, pCollisionProp->GetCollisionAngles(), vSize, vecVelocity, iModelIndex, 100, 1, 2.5, cFlag | slaveFlag ); } } ResetOnGroundFlags(); // Don't fire something that could fire myself SetName( NULL_STRING ); AddSolidFlags( FSOLID_NOT_SOLID ); // Fire targets on break m_OnBreak.FireOutput( m_hBreaker, this ); VPhysicsDestroyObject(); SetThink( &CBreakable::SUB_Remove ); SetNextThink( gpGlobals->curtime + 0.1f ); if ( m_iszSpawnObject != NULL_STRING ) { CBaseEntity::Create( STRING(m_iszSpawnObject), vecSpot, pCollisionProp->GetCollisionAngles(), this ); } if ( Explodable() ) { ExplosionCreate( vecSpot, pCollisionProp->GetCollisionAngles(), this, GetExplosiveDamage(), GetExplosiveRadius(), true ); } }
static void RecvProxy_OBBMaxs( const CRecvProxyData *pData, void *pStruct, void *pOut ) { CCollisionProperty *pProp = ((CCollisionProperty*)pStruct); Vector &vecMaxs = *((Vector*)pData->m_Value.m_Vector); pProp->SetCollisionBounds( pProp->OBBMins(), vecMaxs ); }
IterationRetval_t CPortalCollideableEnumerator::EnumElement( IHandleEntity *pHandleEntity ) { EHANDLE hEnt = pHandleEntity->GetRefEHandle(); CBaseEntity *pEnt = hEnt.Get(); if( pEnt == NULL ) //I really never thought this would be necessary return ITERATION_CONTINUE; if( hEnt == m_hTestPortal ) return ITERATION_CONTINUE; //ignore this portal /*if( staticpropmgr->IsStaticProp( pHandleEntity ) ) { //we're dealing with a static prop, which unfortunately doesn't have everything I want to use for checking ICollideable *pCollideable = pEnt->GetCollideable(); Vector vMins, vMaxs; pCollideable->WorldSpaceSurroundingBounds( &vMins, &vMaxs ); Vector ptTest( (m_vPlaneNormal.x > 0.0f)?(vMaxs.x):(vMins.x), (m_vPlaneNormal.y > 0.0f)?(vMaxs.y):(vMins.y), (m_vPlaneNormal.z > 0.0f)?(vMaxs.z):(vMins.z) ); float fPtPlaneDist = m_vPlaneNormal.Dot( ptTest ) - m_fPlaneDist; if( fPtPlaneDist <= 0.0f ) return ITERATION_CONTINUE; } else*/ { //not a static prop, w00t CCollisionProperty *pEntityCollision = pEnt->CollisionProp(); if( !pEntityCollision->IsSolid() ) return ITERATION_CONTINUE; //not solid Vector ptEntCenter = pEntityCollision->WorldSpaceCenter(); float fBoundRadius = pEntityCollision->BoundingRadius(); float fPtPlaneDist = m_vPlaneNormal.Dot( ptEntCenter ) - m_fPlaneDist; if( fPtPlaneDist < -fBoundRadius ) return ITERATION_CONTINUE; //object wholly behind the portal if( !(fPtPlaneDist > fBoundRadius) && (fPtPlaneDist > -fBoundRadius) ) //object is not wholly in front of the portal, but could be partially in front, do more checks { Vector ptNearest; pEntityCollision->CalcNearestPoint( m_ptForward1000, &ptNearest ); fPtPlaneDist = m_vPlaneNormal.Dot( ptNearest ) - m_fPlaneDist; if( fPtPlaneDist < 0.0f ) return ITERATION_CONTINUE; //closest point was behind the portal plane, we don't want it } } //if we're down here, this entity needs to be added to our enumeration Assert( m_iHandleCount < 1024 ); if( m_iHandleCount < 1024 ) m_pHandles[m_iHandleCount] = pHandleEntity; ++m_iHandleCount; return ITERATION_CONTINUE; }