CRagdollExplosionEnumerator::~CRagdollExplosionEnumerator() { for (int i = 0; i < m_Entities.Count(); i++ ) { C_BaseEntity *pEnt = m_Entities[i]; C_BaseAnimating *pModel = static_cast< C_BaseAnimating * >( pEnt ); Vector position = pEnt->CollisionProp()->GetCollisionOrigin(); Vector dir = position - m_vecOrigin; float dist = VectorNormalize( dir ); float force = m_flMagnitude - ( ( m_flMagnitude / m_flRadius ) * dist ); if ( force <= 1.0f ) continue; trace_t tr; UTIL_TraceLine( m_vecOrigin, position, MASK_SHOT_HULL, NULL, COLLISION_GROUP_NONE, &tr ); // debugoverlay->AddLineOverlay( m_vecOrigin, position, 0,255,0, true, 18.0 ); if ( tr.fraction < 1.0f && tr.m_pEnt != pModel ) continue; dir *= force; // scale force // tricky, adjust tr.start so end-start->= force tr.startpos = tr.endpos - dir; // move expolsion center a bit down, so things fly higher tr.startpos.z -= 32.0f; pModel->ImpactTrace( &tr, DMG_BLAST, NULL ); } }
//----------------------------------------------------------------------------- // Purpose: // Input : fTimeDelta - //----------------------------------------------------------------------------- void C_EntityParticleTrail::Update( float fTimeDelta ) { float tempDelta = fTimeDelta; studiohdr_t *pStudioHdr; mstudiohitboxset_t *set; matrix3x4_t *hitboxbones[MAXSTUDIOBONES]; C_BaseEntity *pMoveParent = GetMoveParent(); if ( !pMoveParent ) return; C_BaseAnimating *pAnimating = pMoveParent->GetBaseAnimating(); if (!pAnimating) goto trailNoHitboxes; if ( !pAnimating->HitboxToWorldTransforms( hitboxbones ) ) goto trailNoHitboxes; pStudioHdr = modelinfo->GetStudiomodel( pAnimating->GetModel() ); if (!pStudioHdr) goto trailNoHitboxes; set = pStudioHdr->pHitboxSet( pAnimating->GetHitboxSet() ); if ( !set ) goto trailNoHitboxes; //Add new particles while ( m_teParticleSpawn.NextEvent( tempDelta ) ) { int nHitbox = random->RandomInt( 0, set->numhitboxes - 1 ); mstudiobbox_t *pBox = set->pHitbox(nHitbox); AddParticle( tempDelta, pBox->bbmin, pBox->bbmax, *hitboxbones[pBox->bone] ); } return; trailNoHitboxes: while ( m_teParticleSpawn.NextEvent( tempDelta ) ) { AddParticle( tempDelta, pMoveParent->CollisionProp()->OBBMins(), pMoveParent->CollisionProp()->OBBMaxs(), pMoveParent->EntityToWorldTransform() ); } }
void CPhysicsSystem::PhysicsSimulate() { VPROF_BUDGET( "CPhysicsSystem::PhysicsSimulate", VPROF_BUDGETGROUP_PHYSICS ); float frametime = gpGlobals->frametime; if ( physenv ) { tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s %d", __FUNCTION__, physenv->GetActiveObjectCount() ); g_Collisions.BufferTouchEvents( true ); #ifdef _DEBUG physenv->DebugCheckContacts(); #endif physenv->Simulate( frametime * cl_phys_timescale.GetFloat() ); int activeCount = physenv->GetActiveObjectCount(); IPhysicsObject **pActiveList = NULL; if ( activeCount ) { pActiveList = (IPhysicsObject **)stackalloc( sizeof(IPhysicsObject *)*activeCount ); physenv->GetActiveObjects( pActiveList ); for ( int i = 0; i < activeCount; i++ ) { C_BaseEntity *pEntity = reinterpret_cast<C_BaseEntity *>(pActiveList[i]->GetGameData()); if ( pEntity ) { if ( pEntity->CollisionProp()->DoesVPhysicsInvalidateSurroundingBox() ) { pEntity->CollisionProp()->MarkSurroundingBoundsDirty(); } pEntity->VPhysicsUpdate( pActiveList[i] ); } } } g_Collisions.BufferTouchEvents( false ); g_Collisions.FrameUpdate(); } physicssound::PlayImpactSounds( m_impactSounds ); }
//----------------------------------------------------------------------------- // Purpose: Create the matrix by which we'll transform the particle's local // space into world space, via the attachment's transform //----------------------------------------------------------------------------- void CLocalSpaceEmitter::SetupTransformMatrix( void ) { IClientRenderable *pRenderable = ClientEntityList().GetClientRenderableFromHandle( m_hEntity ); if ( pRenderable ) { matrix3x4_t mat; if ( pRenderable->GetAttachment( m_nAttachment, mat ) == false ) { // This attachment is bogus! Assert(0); } // Tell the particle effect so it knows Vector origin; MatrixGetColumn( mat, 3, origin ); m_ParticleEffect.SetLocalSpaceTransform( mat ); SetSortOrigin( origin ); C_BaseEntity *pEnt = pRenderable->GetIClientUnknown()->GetBaseEntity(); if ( pEnt ) { Vector vWorldMins, vWorldMaxs; float scale = pEnt->CollisionProp()->BoundingRadius(); vWorldMins[0] = origin[0] - scale; vWorldMins[1] = origin[1] - scale; vWorldMins[2] = origin[2] - scale; vWorldMaxs[0] = origin[0] + scale; vWorldMaxs[1] = origin[1] + scale; vWorldMaxs[2] = origin[2] + scale; GetBinding().SetBBox( vWorldMins, vWorldMaxs, true ); } } // We preapply the local transform because we need to squash it for viewmodel FOV. m_ParticleEffect.SetAutoApplyLocalTransform( false ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_FuncPhysicsRespawnZone::RespawnProps( void ) { for ( int i = 0; i < m_PropList.Count(); i++ ) { if ( m_PropList[i].hClientEntity == INVALID_CLIENTENTITY_HANDLE ) { if ( !CanMovePropAt( m_PropList[i].vecOrigin, -Vector(32,32,32), Vector(32,32,32) ) ) continue; // This is a crappy way to do this C_PhysPropClientside *pEntity = C_PhysPropClientside::CreateNew(); if ( pEntity ) { pEntity->m_spawnflags = m_PropList[i].iSpawnFlags; pEntity->SetModelName( m_PropList[i].iszModelName ); pEntity->SetAbsOrigin( m_PropList[i].vecOrigin ); pEntity->SetAbsAngles( m_PropList[i].vecAngles ); pEntity->SetPhysicsMode( PHYSICS_MULTIPLAYER_CLIENTSIDE ); pEntity->m_nSkin = m_PropList[i].iSkin; pEntity->m_iHealth = m_PropList[i].iHealth; if ( pEntity->m_iHealth == 0 ) { pEntity->m_takedamage = DAMAGE_NO; } if ( !pEntity->Initialize() ) { pEntity->Release(); } else { pEntity->SetRespawnZone( this ); m_PropList[i].hClientEntity = pEntity->GetClientHandle(); } } } else { // If the prop has moved, bring it back C_BaseEntity *pEntity = ClientEntityList().GetBaseEntityFromHandle( m_PropList[i].hClientEntity ); if ( pEntity ) { if ( !CollisionProp()->IsPointInBounds( pEntity->WorldSpaceCenter() ) ) { Vector vecMins, vecMaxs; pEntity->CollisionProp()->WorldSpaceSurroundingBounds( &vecMins, &vecMaxs ); if ( !CanMovePropAt( m_PropList[i].vecOrigin, vecMins, vecMaxs ) || !CanMovePropAt( pEntity->GetAbsOrigin(), vecMins, vecMaxs ) ) continue; pEntity->SetAbsOrigin( m_PropList[i].vecOrigin ); pEntity->SetAbsAngles( m_PropList[i].vecAngles ); IPhysicsObject *pPhys = pEntity->VPhysicsGetObject(); if ( pPhys ) { pPhys->SetPosition( pEntity->GetAbsOrigin(), pEntity->GetAbsAngles(), true ); } } } } } }
void FX_ThumperDust( const CEffectData &data ) { Vector vecDustColor; vecDustColor.x = 0.85f; vecDustColor.y = 0.75f; vecDustColor.z = 0.52f; CSmartPtr<ThumperDustEmitter> pSimple = ThumperDustEmitter::Create( "thumperdust" ); C_BaseEntity *pEnt = C_BaseEntity::Instance( data.m_hEntity ); if ( pEnt ) { Vector vWorldMins, vWorldMaxs; float scale = pEnt->CollisionProp()->BoundingRadius(); vWorldMins[0] = data.m_vOrigin[0] - scale; vWorldMins[1] = data.m_vOrigin[1] - scale; vWorldMins[2] = data.m_vOrigin[2] - scale; vWorldMaxs[0] = data.m_vOrigin[0] + scale; vWorldMaxs[1] = data.m_vOrigin[1] + scale; vWorldMaxs[2] = data.m_vOrigin[2] + scale; pSimple->GetBinding().SetBBox( vWorldMins, vWorldMaxs, true ); } pSimple->SetSortOrigin( data.m_vOrigin ); pSimple->SetNearClip( 32, 64 ); SimpleParticle *pParticle = NULL; Vector offset; //int numPuffs = IsXbox() ? THUMPER_MAX_PARTICLES/2 : THUMPER_MAX_PARTICLES; int numPuffs = THUMPER_MAX_PARTICLES; float flYaw = 0; float flIncr = (2*M_PI) / (float) numPuffs; // Radians Vector forward; Vector vecColor; int i = 0; float flScale = min( data.m_flScale, 255 ); // Setup the color for these particles engine->ComputeLighting( data.m_vOrigin, NULL, true, vecColor ); VectorLerp( vecColor, vecDustColor, 0.5, vecColor ); vecColor *= 255; for ( i = 0; i < numPuffs; i++ ) { flYaw += flIncr; SinCos( flYaw, &forward.y, &forward.x ); forward.z = 0.0f; offset = ( RandomVector( -4.0f, 4.0f ) + data.m_vOrigin ) + ( forward * 128.0f ); pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof(SimpleParticle), g_Mat_DustPuff[random->RandomInt(0,1)], offset ); if ( pParticle != NULL ) { pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = 1.5f; Vector dir = (offset - data.m_vOrigin); float length = dir.Length(); VectorNormalize( dir ); pParticle->m_vecVelocity = dir * ( length * 2.0f ); pParticle->m_vecVelocity[2] = data.m_flScale / 3; pParticle->m_uchColor[0] = vecColor[0]; pParticle->m_uchColor[1] = vecColor[1]; pParticle->m_uchColor[2] = vecColor[2]; pParticle->m_uchStartAlpha = random->RandomInt( 64, 96 ); pParticle->m_uchEndAlpha = 0; pParticle->m_uchStartSize = flScale * 0.25f; pParticle->m_uchEndSize = flScale * 0.5f; pParticle->m_flRoll = random->RandomInt( 0, 360 ); pParticle->m_flRollDelta = random->RandomFloat( -6.0f, 6.0f ); } } }
void CPhysicsSystem::PhysicsSimulate() { CMiniProfilerGuard mpg(&g_mp_PhysicsSimulate); VPROF_BUDGET( "CPhysicsSystem::PhysicsSimulate", VPROF_BUDGETGROUP_PHYSICS ); float frametime = gpGlobals->frametime; if ( physenv ) { g_Collisions.BufferTouchEvents( true ); #ifdef _DEBUG physenv->DebugCheckContacts(); #endif frametime *= cl_phys_timescale.GetFloat(); int maxTicks = cl_phys_maxticks.GetInt(); if ( maxTicks ) { float maxFrameTime = physenv->GetDeltaFrameTime( maxTicks ) - 1e-4f; frametime = clamp( frametime, 0, maxFrameTime ); } physenv->Simulate( frametime ); int activeCount = physenv->GetActiveObjectCount(); g_mp_active_object_count.Add(activeCount); IPhysicsObject **pActiveList = NULL; if ( activeCount ) { PHYS_PROFILE(aUpdateActiveObjects) pActiveList = (IPhysicsObject **)stackalloc( sizeof(IPhysicsObject *)*activeCount ); physenv->GetActiveObjects( pActiveList ); for ( int i = 0; i < activeCount; i++ ) { C_BaseEntity *pEntity = reinterpret_cast<C_BaseEntity *>(pActiveList[i]->GetGameData()); if ( pEntity ) { //const CCollisionProperty *collProp = pEntity->CollisionProp(); //debugoverlay->AddBoxOverlay( collProp->GetCollisionOrigin(), collProp->OBBMins(), collProp->OBBMaxs(), collProp->GetCollisionAngles(), 190, 190, 0, 0, 0.01 ); if ( pEntity->CollisionProp()->DoesVPhysicsInvalidateSurroundingBox() ) { pEntity->CollisionProp()->MarkSurroundingBoundsDirty(); } pEntity->VPhysicsUpdate( pActiveList[i] ); IPhysicsShadowController *pShadow = pActiveList[i]->GetShadowController(); if ( pShadow ) { // active shadow object, check for error Vector pos, targetPos; QAngle rot, targetAngles; pShadow->GetTargetPosition( &targetPos, &targetAngles ); pActiveList[i]->GetPosition( &pos, &rot ); Vector delta = targetPos - pos; float dist = VectorNormalize(delta); bool bBlocked = false; if ( dist > cl_phys_block_dist.GetFloat() ) { Vector vel; pActiveList[i]->GetImplicitVelocity( &vel, NULL ); float proj = DotProduct(vel, delta); if ( proj < dist * cl_phys_block_fraction.GetFloat() ) { bBlocked = true; //Msg("%s was blocked %.3f (%.3f proj)!\n", pEntity->GetClassname(), dist, proj ); } } Vector targetAxis; float deltaTargetAngle; RotationDeltaAxisAngle( rot, targetAngles, targetAxis, deltaTargetAngle ); if ( fabsf(deltaTargetAngle) > 0.5f ) { AngularImpulse angVel; pActiveList[i]->GetImplicitVelocity( NULL, &angVel ); float proj = DotProduct( angVel, targetAxis ) * Sign(deltaTargetAngle); if ( proj < (fabsf(deltaTargetAngle) * cl_phys_block_fraction.GetFloat()) ) { bBlocked = true; //Msg("%s was rot blocked %.3f proj %.3f!\n", pEntity->GetClassname(), deltaTargetAngle, proj ); } } if ( bBlocked ) { C_BaseEntity *pBlocker = FindPhysicsBlocker( pActiveList[i] ); if ( pBlocker ) { if ( IsBlockedShouldDisableCollisions( pEntity ) ) { PhysDisableEntityCollisions( pEntity, pBlocker ); pActiveList[i]->RecheckContactPoints(); // GetClassname returns a pointer to the same buffer always! //Msg("%s blocked !", pEntity->GetClassname() ); Msg("by %s\n", pBlocker->GetClassname() ); } } } } } } } #if 0 if ( cl_visualize_physics_shadows.GetBool() ) { int entityCount = NUM_ENT_ENTRIES; for ( int i = 0; i < entityCount; i++ ) { IClientEntity *pClientEnt = cl_entitylist->GetClientEntity(i); if ( !pClientEnt ) continue; C_BaseEntity *pEntity = pClientEnt->GetBaseEntity(); if ( !pEntity ) continue; Vector pos; QAngle angle; IPhysicsObject *pObj = pEntity->VPhysicsGetObject(); if ( !pObj || !pObj->GetShadowController() ) continue; pObj->GetShadowPosition( &pos, &angle ); debugoverlay->AddBoxOverlay( pos, pEntity->CollisionProp()->OBBMins(), pEntity->CollisionProp()->OBBMaxs(), angle, 255, 255, 0, 32, 0 ); char tmp[256]; V_snprintf( tmp, sizeof(tmp),"%s, (%s)\n", pEntity->GetClassname(), VecToString(angle) ); debugoverlay->AddTextOverlay( pos, 0, tmp ); } } #endif g_Collisions.BufferTouchEvents( false ); g_Collisions.FrameUpdate(); } physicssound::PlayImpactSounds( m_impactSounds ); }