//----------------------------------------------------------------------------- // 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; } } }
//----------------------------------------------------------------------------- // Updates the spatial partition //----------------------------------------------------------------------------- void CCollisionProperty::UpdatePartition( ) { if ( m_pOuter->IsEFlagSet( EFL_DIRTY_SPATIAL_PARTITION ) ) { m_pOuter->RemoveEFlags( EFL_DIRTY_SPATIAL_PARTITION ); #ifndef CLIENT_DLL Assert( m_pOuter->entindex() != 0 ); // Don't bother with deleted things if ( !m_pOuter->edict() ) return; if ( GetPartitionHandle() == PARTITION_INVALID_HANDLE ) { CreatePartitionHandle(); UpdateServerPartitionMask(); } #else if ( GetPartitionHandle() == PARTITION_INVALID_HANDLE ) return; #endif // We don't need to bother if it's not a trigger or solid if ( IsSolid() || IsSolidFlagSet( FSOLID_TRIGGER ) || m_pOuter->IsEFlagSet( EFL_USE_PARTITION_WHEN_NOT_SOLID ) ) { // Bloat a little bit... if ( BoundingRadius() != 0.0f ) { Vector vecSurroundMins, vecSurroundMaxs; WorldSpaceSurroundingBounds( &vecSurroundMins, &vecSurroundMaxs ); vecSurroundMins -= Vector( 1, 1, 1 ); vecSurroundMaxs += Vector( 1, 1, 1 ); partition->ElementMoved( GetPartitionHandle(), vecSurroundMins, vecSurroundMaxs ); } else { partition->ElementMoved( GetPartitionHandle(), GetCollisionOrigin(), GetCollisionOrigin() ); } } } }
/// Helper function for Fire() -- actually emit the "bullets" of flame or ice void CASW_Sentry_Top_Flamer::FireProjectiles( int numShotsToFire, ///< number of pellets to fire this frame const Vector &vecSrc, ///< origin for bullets const Vector &vecAiming, ///< aim direction for bullets const AngularImpulse &rotSpeed ) { CShotManipulator Manipulator( vecAiming ); CASW_Marine * RESTRICT const pMarineDeployer = GetSentryBase()->m_hDeployer.Get(); Assert( pMarineDeployer ); for ( int i = 0 ; i < numShotsToFire ; i++ ) { // create a pellet at some random spread direction Vector projectileVel = Manipulator.GetShotDirection(); // Manipulator.ApplySpread(GetBulletSpread()); projectileVel *= GetProjectileVelocity(); projectileVel *= (1.0 + (0.1 * random->RandomFloat(-1,1))); CASW_Flamer_Projectile *pFlames = CASW_Flamer_Projectile::Flamer_Projectile_Create( GetSentryDamage(), vecSrc + (projectileVel.Normalized() * BoundingRadius()), QAngle(0,0,0), projectileVel, rotSpeed, this, pMarineDeployer, this ); pFlames->SetHurtIgnited( true ); } }