//----------------------------------------------------------------------------- // Purpose: This think function simulates (moves/collides) the HeadcrabCanister while in // the world. //----------------------------------------------------------------------------- void CEnvHeadcrabCanister::HeadcrabCanisterWorldThink( void ) { // Get the current time. float flTime = gpGlobals->curtime; Vector vecStartPosition = GetAbsOrigin(); // Update HeadcrabCanister position for swept collision test. Vector vecEndPosition; QAngle vecEndAngles; m_Shared.GetPositionAtTime( flTime, vecEndPosition, vecEndAngles ); if ( !m_bIncomingSoundStarted && !HasSpawnFlags( SF_NO_IMPACT_SOUND ) ) { float flDistSq = ENV_HEADCRABCANISTER_INCOMING_SOUND_TIME * m_Shared.m_flFlightSpeed; flDistSq *= flDistSq; if ( vecEndPosition.DistToSqr(m_vecImpactPosition) <= flDistSq ) { // Figure out if we're close enough to play the incoming sound EmitSound( "HeadcrabCanister.IncomingSound" ); m_bIncomingSoundStarted = true; } } TestForCollisionsAgainstEntities( vecEndPosition ); if ( m_Shared.DidImpact( flTime ) ) { if ( !m_bHasDetonated ) { Detonate(); m_bHasDetonated = true; } if ( !HasSpawnFlags( SF_REMOVE_ON_IMPACT ) ) { Landed(); } return; } // Always move full movement. SetAbsOrigin( vecEndPosition ); // Touch triggers along the way PhysicsTouchTriggers( &vecStartPosition ); SetNextThink( gpGlobals->curtime + 0.2f ); SetAbsAngles( vecEndAngles ); if ( !m_bHasDetonated ) { if ( vecEndPosition.DistToSqr( m_vecImpactPosition ) < BoundingRadius() * BoundingRadius() ) { Detonate(); m_bHasDetonated = true; } } }
void CRagdollProp::UpdateNetworkDataFromVPhysics( IPhysicsObject *pPhysics, int index ) { Assert(index < m_ragdoll.listCount); QAngle angles; Vector vPos; m_ragdoll.list[index].pObject->GetPosition( &vPos, &angles ); m_ragPos.Set( index, vPos ); m_ragAngles.Set( index, angles ); // move/relink if root moved if ( index == 0 ) { SetAbsOrigin( m_ragPos[0] ); PhysicsTouchTriggers(); } }
void CRagdollProp::VPhysicsUpdate( IPhysicsObject *pPhysics ) { if ( m_lastUpdateTickCount == (unsigned int)gpGlobals->tickcount ) return; m_lastUpdateTickCount = gpGlobals->tickcount; //NetworkStateChanged(); matrix3x4_t boneToWorld[MAXSTUDIOBONES]; QAngle angles; Vector surroundingMins, surroundingMaxs; if ( m_ragdoll.pGroup->IsInErrorState() ) { RagdollSolveSeparation( m_ragdoll, this ); } int i; for ( i = 0; i < m_ragdoll.listCount; i++ ) { CBoneAccessor boneaccessor( boneToWorld ); RagdollGetBoneMatrix( m_ragdoll, boneaccessor, i ); Vector vNewPos; MatrixAngles( boneToWorld[m_ragdoll.boneIndex[i]], angles, vNewPos ); m_ragPos.Set( i, vNewPos ); m_ragAngles.Set( i, angles ); } // BUGBUG: Use the ragdollmins/maxs to do this instead of the collides m_allAsleep = RagdollIsAsleep( m_ragdoll ); // Don't scream after you've come to rest if ( m_allAsleep ) { m_strSourceClassName = NULL_STRING; } // Interactive debris converts back to debris when it comes to rest if ( m_allAsleep && GetCollisionGroup() == COLLISION_GROUP_INTERACTIVE_DEBRIS ) { SetCollisionGroup( COLLISION_GROUP_DEBRIS ); RecheckCollisionFilter(); SetContextThink( NULL, gpGlobals->curtime, s_pDebrisContext ); } Vector vecFullMins, vecFullMaxs; vecFullMins = m_ragPos[0]; vecFullMaxs = m_ragPos[0]; for ( i = 0; i < m_ragdoll.listCount; i++ ) { Vector mins, maxs; matrix3x4_t update; m_ragdoll.list[i].pObject->GetPositionMatrix( &update ); TransformAABB( update, m_ragdollMins[i], m_ragdollMaxs[i], mins, maxs ); for ( int j = 0; j < 3; j++ ) { if ( mins[j] < vecFullMins[j] ) { vecFullMins[j] = mins[j]; } if ( maxs[j] > vecFullMaxs[j] ) { vecFullMaxs[j] = maxs[j]; } } } SetAbsOrigin( m_ragPos[0] ); SetAbsAngles( vec3_angle ); const Vector &vecOrigin = CollisionProp()->GetCollisionOrigin(); CollisionProp()->AddSolidFlags( FSOLID_FORCE_WORLD_ALIGNED ); CollisionProp()->SetSurroundingBoundsType( USE_COLLISION_BOUNDS_NEVER_VPHYSICS ); SetCollisionBounds( vecFullMins - vecOrigin, vecFullMaxs - vecOrigin ); CollisionProp()->MarkSurroundingBoundsDirty(); PhysicsTouchTriggers(); }