Vector Pickup_PhysGunLaunchVelocity( CBaseEntity *pObject, const Vector &vecForward, PhysGunForce_t reason ) { // The object must be valid if ( pObject == NULL ) { Assert( 0 ); return vec3_origin; } // Shouldn't ever get here with a non-vphysics object. IPhysicsObject *pPhysicsObject = pObject->VPhysicsGetObject(); if ( pPhysicsObject == NULL ) { Assert( 0 ); return vec3_origin; } // Call the pickup entity's callback IPlayerPickupVPhysics *pPickup = dynamic_cast<IPlayerPickupVPhysics *>(pObject); if ( pPickup != NULL && pPickup->ShouldPuntUseLaunchForces( reason ) ) return pPickup->PhysGunLaunchVelocity( vecForward, pPhysicsObject->GetMass() ); // Do our default behavior return Pickup_DefaultPhysGunLaunchVelocity( vecForward, pPhysicsObject->GetMass() ); }
//----------------------------------------------------------------------------- // Purpose: Adds the entity's mass to the aggregate mass consumed //----------------------------------------------------------------------------- void CGravityVortexController::ConsumeEntity( CBaseEntity *pEnt ) { // Get our base physics object IPhysicsObject *pPhysObject = pEnt->VPhysicsGetObject(); if ( pPhysObject == NULL ) return; // Ragdolls need to report the sum of all their parts CRagdollProp *pRagdoll = dynamic_cast< CRagdollProp* >( pEnt ); if ( pRagdoll != NULL ) { // Find the aggregate mass of the whole ragdoll ragdoll_t *pRagdollPhys = pRagdoll->GetRagdoll(); for ( int j = 0; j < pRagdollPhys->listCount; ++j ) { m_flMass += pRagdollPhys->list[j].pObject->GetMass(); } } else { // Otherwise we just take the normal mass m_flMass += pPhysObject->GetMass(); } // Destroy the entity UTIL_Remove( pEnt ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- int CPhysBox::OnTakeDamage( const CTakeDamageInfo &info ) { // note: if motion is disabled, OnTakeDamage can't apply physics force int ret = BaseClass::OnTakeDamage( info ); // Check our health against the threshold: if( m_damageToEnableMotion > 0 && GetHealth() < m_damageToEnableMotion ) { // only do this once m_damageToEnableMotion = 0; IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); if ( pPhysicsObject != NULL ) { pPhysicsObject->Wake(); pPhysicsObject->EnableMotion( true ); VPhysicsTakeDamage( info ); } } if ( info.GetInflictor() ) { m_OnDamaged.FireOutput( info.GetAttacker(), this ); } return ret; }
void CPhysicsSpring::GetSpringObjectConnections( string_t nameStart, string_t nameEnd, IPhysicsObject **pStart, IPhysicsObject **pEnd ) { IPhysicsObject *pStartObject = FindPhysicsObject( STRING(nameStart) ); IPhysicsObject *pEndObject = FindPhysicsObject( STRING(nameEnd) ); // Assume the world for missing objects if ( !pStartObject ) { pStartObject = g_PhysWorldObject; } else if ( !pEndObject ) { // try to sort so that the world is always the start object pEndObject = pStartObject; pStartObject = g_PhysWorldObject; } else { CBaseEntity *pEntity0 = (CBaseEntity *) (pStartObject->GetGameData()); g_pNotify->AddEntity( this, pEntity0 ); CBaseEntity *pEntity1 = (CBaseEntity *) pEndObject->GetGameData(); g_pNotify->AddEntity( this, pEntity1 ); } *pStart = pStartObject; *pEnd = pEndObject; }
void C_HL2MPRagdoll::ImpactTrace( trace_t *pTrace, int iDamageType, const char *pCustomImpactName ) { IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); if( !pPhysicsObject ) return; Vector dir = pTrace->endpos - pTrace->startpos; if ( iDamageType == DMG_BLAST ) { dir *= 4000; // adjust impact strenght // apply force at object mass center pPhysicsObject->ApplyForceCenter( dir ); } else { Vector hitpos; VectorMA( pTrace->startpos, pTrace->fraction, dir, hitpos ); VectorNormalize( dir ); dir *= 4000; // adjust impact strenght // apply force where we hit it pPhysicsObject->ApplyForceOffset( dir, hitpos ); // Blood spray! // FX_CS_BloodSpray( hitpos, dir, 10 ); } m_pRagdoll->ResetRagdollSleepAfterTime(); }
// as CItem, but we don't install the touch function void CASW_Pickup::Spawn( void ) { SetMoveType( MOVETYPE_FLYGRAVITY ); SetSolid( SOLID_BBOX ); SetBlocksLOS( false ); AddEFlags( EFL_NO_ROTORWASH_PUSH ); // This will make them not collide with the player, but will collide // against other items + weapons SetCollisionGroup( COLLISION_GROUP_WEAPON ); CollisionProp()->UseTriggerBounds( true, ITEM_PICKUP_BOX_BLOAT ); //SetTouch(&CItem::ItemTouch); if ( CreateItemVPhysicsObject() == false ) return; m_takedamage = DAMAGE_EVENTS_ONLY; #ifdef HL2MP SetThink( &CItem::FallThink ); SetNextThink( gpGlobals->curtime + 0.1f ); #endif if ( m_bFreezePickup ) { IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); if ( pPhysicsObject != NULL ) { pPhysicsObject->EnableMotion( false ); } } }
void CEnvHeadcrabCanister::TestForCollisionsAgainstWorld( const Vector &vecEndPosition ) { // Splash damage! // Iterate on all entities in the vicinity. float flDamageRadius = m_flDamageRadius; float flDamage = m_flDamage; CEntity *pEntity; for ( CEntitySphereQuery sphere( vecEndPosition, flDamageRadius ); ( pEntity = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() ) { if ( pEntity == this ) continue; if ( !pEntity->IsSolid() ) continue; // Get distance to object and use it as a scale value. Vector vecSegment; VectorSubtract( pEntity->GetAbsOrigin(), vecEndPosition, vecSegment ); float flDistance = VectorNormalize( vecSegment ); float flFactor = 1.0f / ( flDamageRadius * (INNER_RADIUS_FRACTION - 1) ); flFactor *= flFactor; float flScale = flDistance - flDamageRadius; flScale *= flScale * flFactor; if ( flScale > 1.0f ) { flScale = 1.0f; } // Check for a physics object and apply force! Vector vecForceDir = vecSegment; IPhysicsObject *pPhysObject = pEntity->VPhysicsGetObject(); if ( pPhysObject ) { // Send it flying!!! float flMass = PhysGetEntityMass( pEntity ); vecForceDir *= flMass * 750 * flScale; pPhysObject->ApplyForceCenter( vecForceDir ); } if ( pEntity->m_takedamage && ( m_flDamage != 0.0f ) ) { CTakeDamageInfo info( BaseEntity(), BaseEntity(), flDamage * flScale, DMG_BLAST ); CalculateExplosiveDamageForce( &info, vecSegment, pEntity->GetAbsOrigin() ); pEntity->TakeDamage( info ); } if ( pEntity->IsPlayer() && !(static_cast<CPlayer*>(pEntity)->IsInAVehicle()) ) { if (vecSegment.z < 0.1f) { vecSegment.z = 0.1f; VectorNormalize( vecSegment ); } float flAmount = SimpleSplineRemapVal( flScale, 0.0f, 1.0f, 250.0f, 1000.0f ); pEntity->ApplyAbsVelocityImpulse( vecSegment * flAmount ); } } }
//----------------------------------------------------------------------------- // Purpose: // Input : // Output : //----------------------------------------------------------------------------- int CTDP_NPC_CombineS::TakeDamage( const CTakeDamageInfo &info ) { if( info.GetInflictor() && info.GetInflictor()->VPhysicsGetObject() ) { // Hit by a physics object! Was I blocking? if( m_fIsBlocking ) { IPhysicsObject *pPhysObject; pPhysObject = info.GetInflictor()->VPhysicsGetObject(); if( pPhysObject ) { // Only deflect objects of relatively low mass //DevMsg( "MASS: %f\n", pPhysObject->GetMass() ); if( pPhysObject->GetMass() <= 30.0 ) { // No damage from light objects (tuned for melons) return 0; } } } } BaseClass::TakeDamage( info ); return 0; }
//----------------------------------------------------------------------------- // Step iteratively toward a destination position //----------------------------------------------------------------------------- AIMotorMoveResult_t CAI_Motor::MoveGroundStep( const Vector &newPos, CBaseEntity *pMoveTarget, float yaw, bool bAsFarAsCan, AIMoveTrace_t *pTraceResult ) { // By definition, this will produce different results than GroundMoveLimit() // because there's no guarantee that it will step exactly one step // See how far toward the new position we can step... // But don't actually test for ground geometric validity; // if it isn't valid, there's not much we can do about it AIMoveTrace_t moveTrace; GetMoveProbe()->TestGroundMove( GetLocalOrigin(), newPos, MASK_NPCSOLID, AITGM_IGNORE_FLOOR, &moveTrace ); if ( pTraceResult ) { *pTraceResult = moveTrace; } bool bHitTarget = (moveTrace.pObstruction && (pMoveTarget == moveTrace.pObstruction )); // Move forward either if there was no obstruction or if we're told to // move as far as we can, regardless bool bIsBlocked = IsMoveBlocked(moveTrace.fStatus); if ( !bIsBlocked || bAsFarAsCan || bHitTarget ) { // The true argument here causes it to touch all triggers // in the volume swept from the previous position to the current position UTIL_SetOrigin(GetOuter(), moveTrace.vEndPosition, true); // skip tiny steps, but notify the shadow object of any large steps if ( moveTrace.flStepUpDistance > 0.1f ) { float height = clamp( moveTrace.flStepUpDistance, 0, StepHeight() ); IPhysicsObject *pPhysicsObject = GetOuter()->VPhysicsGetObject(); if ( pPhysicsObject ) { IPhysicsShadowController *pShadow = pPhysicsObject->GetShadowController(); if ( pShadow ) { pShadow->StepUp( height ); } } } if ( yaw != -1 ) { QAngle angles = GetLocalAngles(); angles.y = yaw; SetLocalAngles( angles ); } if ( bHitTarget ) return AIM_PARTIAL_HIT_TARGET; if ( !bIsBlocked ) return AIM_SUCCESS; if ( moveTrace.fStatus == AIMR_BLOCKED_NPC ) return AIM_PARTIAL_HIT_NPC; return AIM_PARTIAL_HIT_WORLD; } return AIM_FAILED; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool CPropJeep::CheckWater( void ) { bool bInWater = false; // Check all four wheels. for ( int iWheel = 0; iWheel < JEEP_WHEEL_COUNT; ++iWheel ) { // Get the current wheel and get its contact point. IPhysicsObject *pWheel = m_VehiclePhysics.GetWheel( iWheel ); if ( !pWheel ) continue; // Check to see if we hit water. if ( pWheel->GetContactPoint( &m_WaterData.m_vecWheelContactPoints[iWheel], NULL ) ) { m_WaterData.m_bWheelInWater[iWheel] = ( UTIL_PointContents( m_WaterData.m_vecWheelContactPoints[iWheel] ) & MASK_WATER ) ? true : false; if ( m_WaterData.m_bWheelInWater[iWheel] ) { bInWater = true; } } } // Check the body and the BONNET. int iEngine = LookupAttachment( "vehicle_engine" ); Vector vecEnginePoint; QAngle vecEngineAngles; GetAttachment( iEngine, vecEnginePoint, vecEngineAngles ); m_WaterData.m_bBodyInWater = ( UTIL_PointContents( vecEnginePoint ) & MASK_WATER ) ? true : false; if ( m_WaterData.m_bBodyInWater ) { if ( m_bHasPoop ) { RemoveAllDecals(); m_bHasPoop = false; } if ( !m_VehiclePhysics.IsEngineDisabled() ) { m_VehiclePhysics.SetDisableEngine( true ); } } else { if ( m_VehiclePhysics.IsEngineDisabled() ) { m_VehiclePhysics.SetDisableEngine( false ); } } if ( bInWater ) { // Check the player's water level. CheckWaterLevel(); } return bInWater; }
//----------------------------------------------------------------------------- // Purpose: Disable any physics motion or collision response //----------------------------------------------------------------------------- void CPhysBox::InputDisableMotion( inputdata_t &inputdata ) { IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); if ( pPhysicsObject != NULL ) { pPhysicsObject->EnableMotion( false ); } }
//----------------------------------------------------------------------------- // Purpose: Input handler for waking up the cannister if it is sleeping. //----------------------------------------------------------------------------- void CPhysicsCannister::InputWake( inputdata_t &data ) { IPhysicsObject *pPhys = VPhysicsGetObject(); if ( pPhys != NULL ) { pPhys->Wake(); } }
void CTripwireHook::SetVelocity( const Vector &velocity, const AngularImpulse &angVelocity ) { IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); if ( pPhysicsObject ) { pPhysicsObject->AddVelocity( &velocity, &angVelocity ); } }
void CGETKnife::SetVelocity( const Vector &velocity, const AngularImpulse &angVelocity ) { IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); if ( pPhysicsObject ) { pPhysicsObject->SetVelocityInstantaneous( &velocity, &angVelocity ); } }
void CBaseGrenadeProjectile::SetVelocity( const Vector &velocity, const AngularImpulse &angVelocity ) { IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); if ( pPhysicsObject ) { pPhysicsObject->AddVelocity( &velocity, &angVelocity ); } }
void CRagdollPropAttached::InitRagdollAttached( IPhysicsObject *pAttached, const Vector &forceVector, int forceBone, matrix3x4_t *pPrevBones, matrix3x4_t *pBoneToWorld, float dt, int collisionGroup, CBaseAnimating *pFollow, int boneIndexRoot, const Vector &boneLocalOrigin, int parentBoneAttach, const Vector &worldAttachOrigin ) { int ragdollAttachedIndex = 0; if ( parentBoneAttach > 0 ) { studiohdr_t *pStudioHdr = GetModelPtr(); mstudiobone_t *pBone = pStudioHdr->pBone( parentBoneAttach ); ragdollAttachedIndex = pBone->physicsbone; } InitRagdoll( forceVector, forceBone, vec3_origin, pPrevBones, pBoneToWorld, dt, collisionGroup, false ); IPhysicsObject *pRefObject = m_ragdoll.list[ragdollAttachedIndex].pObject; Vector attachmentPointRagdollSpace; pRefObject->WorldToLocal( attachmentPointRagdollSpace, worldAttachOrigin ); constraint_ragdollparams_t constraint; constraint.Defaults(); matrix3x4_t tmp, worldToAttached, worldToReference, constraintToWorld; Vector offsetWS; pAttached->LocalToWorld( offsetWS, boneLocalOrigin ); AngleMatrix( QAngle(0, pFollow->GetAbsAngles().y, 0 ), offsetWS, constraintToWorld ); constraint.axes[0].SetAxisFriction( -2, 2, 20 ); constraint.axes[1].SetAxisFriction( 0, 0, 0 ); constraint.axes[2].SetAxisFriction( -15, 15, 20 ); pAttached->GetPositionMatrix( tmp ); MatrixInvert( tmp, worldToAttached ); pRefObject->GetPositionMatrix( tmp ); MatrixInvert( tmp, worldToReference ); ConcatTransforms( worldToReference, constraintToWorld, constraint.constraintToReference ); ConcatTransforms( worldToAttached, constraintToWorld, constraint.constraintToAttached ); // for now, just slam this to be the passed in value MatrixSetColumn( attachmentPointRagdollSpace, 3, constraint.constraintToReference ); DisableCollisions( pAttached ); m_pAttachConstraint = physenv->CreateRagdollConstraint( pRefObject, pAttached, m_ragdoll.pGroup, constraint ); FollowEntity( pFollow ); SetOwnerEntity( pFollow ); RagdollActivate( m_ragdoll ); Relink(); m_boneIndexAttached = boneIndexRoot; m_ragdollAttachedObjectIndex = ragdollAttachedIndex; m_attachmentPointBoneSpace = boneLocalOrigin; Vector vTemp; MatrixGetColumn( constraint.constraintToReference, 3, vTemp ); m_attachmentPointRagdollSpace = vTemp; }
//DHL - Skillet - Fix ammo exploits void CWeaponFrag::Drop( const Vector &vecVelocity ) { if ( !HasPrimaryAmmo() ) { //BaseClass::Drop( vecVelocity ); SUB_Remove(); return; } if ( !GetOwner() ) return; DecrementAmmo( GetOwner() ); Reload(); //Do draw animation and stuff #ifndef CLIENT_DLL CBasePlayer *owner = ToBasePlayer(GetOwner()); Vector vThrowPos = owner->Weapon_ShootPosition() - Vector(0,0,12); //Create a grenade CBaseCombatWeapon* pGrenade; pGrenade = (CBaseCombatWeapon *)CBaseEntity::Create( "weapon_frag", vThrowPos, vec3_angle, NULL ); if ( !pGrenade ) return; pGrenade->SetRemoveable( true ); //If it was dropped then there's no need to respawn it. pGrenade->AddSpawnFlags( SF_NORESPAWN ); pGrenade->StopAnimation(); pGrenade->StopFollowingEntity( ); pGrenade->SetMoveType( MOVETYPE_FLYGRAVITY ); // clear follow stuff, setup for collision pGrenade->SetGravity(1.0); pGrenade->m_iState = WEAPON_NOT_CARRIED; pGrenade->RemoveEffects( EF_NODRAW ); pGrenade->FallInit(); pGrenade->SetGroundEntity( NULL ); pGrenade->SetTouch(NULL); pGrenade->SetOwnerEntity( NULL ); pGrenade->SetOwner( NULL ); //Toss it in the direction of the player's view Vector vecNewVelocity; Vector vecDir; owner->EyeVectors( &vecDir ); vecNewVelocity = ( vecDir * 500.0f ); IPhysicsObject *pObj = pGrenade->VPhysicsGetObject(); if ( pObj != NULL ) { AngularImpulse angImp( 200, 200, 200 ); pObj->AddVelocity( &vecNewVelocity, &angImp ); } #endif }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CGrenadeHopwire::SetVelocity( const Vector &velocity, const AngularImpulse &angVelocity ) { IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); if ( pPhysicsObject != NULL ) { pPhysicsObject->AddVelocity( &velocity, &angVelocity ); } }
void CPlayerPickupController::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { if ( ToBasePlayer(pActivator) == m_pPlayer ) { CBaseEntity *pAttached = m_grabController.GetAttached(); // UNDONE: Use vphysics stress to decide to drop objects // UNDONE: Must fix case of forcing objects into the ground you're standing on (causes stress) before that will work if ( !pAttached || useType == USE_OFF || (m_pPlayer->m_nButtons & IN_ATTACK2) || m_grabController.ComputeError() > 12 ) { Shutdown(); return; } //Adrian: Oops, our object became motion disabled, let go! IPhysicsObject *pPhys = pAttached->VPhysicsGetObject(); if ( pPhys && pPhys->IsMoveable() == false ) { Shutdown(); return; } #if STRESS_TEST vphysics_objectstress_t stress; CalculateObjectStress( pPhys, pAttached, &stress ); if ( stress.exertedStress > 250 ) { Shutdown(); return; } #endif #ifndef PLAYER_DISABLE_THROWING // +ATTACK will throw phys objects if ( m_pPlayer->m_nButtons & IN_ATTACK ) { Shutdown( true ); Vector vecLaunch; m_pPlayer->EyeVectors( &vecLaunch ); // JAY: Scale this with mass because some small objects really go flying float massFactor = clamp( pPhys->GetMass(), 0.5, 15 ); massFactor = RemapVal( massFactor, 0.5, 15, 0.5, 4 ); vecLaunch *= player_throwforce.GetFloat() * massFactor; pPhys->ApplyForceCenter( vecLaunch ); AngularImpulse aVel = RandomAngularImpulse( -10, 10 ) * massFactor; pPhys->ApplyTorqueCenter( aVel ); return; } #endif if ( useType == USE_SET ) { // update position m_grabController.UpdateObject( m_pPlayer, 12 ); } } }
void CFuncVehicleClip::InputDisable( inputdata_t &data ) { IPhysicsObject *pPhys = VPhysicsGetObject(); if ( pPhys ) { pPhys->EnableCollisions( false ); } AddSolidFlags( FSOLID_NOT_SOLID ); }
void CFuncVehicleClip::InputEnable( inputdata_t &data ) { IPhysicsObject *pPhys = VPhysicsGetObject(); if ( pPhys ) { pPhys->EnableCollisions( true ); } RemoveSolidFlags( FSOLID_NOT_SOLID ); }
void QueueSave( CBaseEntity *pOwner, typedescription_t *pTypeDesc, void **ppPhysObj, PhysInterfaceId_t type ) { if ( !pOwner ) return; bool fOnlyNotingExistence = !pOwner->ShouldSavePhysics(); QueuedItem_t item; item.ppPhysObj = ppPhysObj; item.header.hEntity = pOwner; item.header.type = type; item.header.nObjects = ( !fOnlyNotingExistence ) ? pTypeDesc->fieldSize : 0; item.header.fieldName = AllocPooledString( pTypeDesc->fieldName ); // A pooled string is used here because there is no way // right now to save a non-string_t string and have it // compressed in the save symbol tables. Furthermore, // the field name would normally be in the string // pool anyway. (toml 12-10-02) item.header.modelName = NULL_STRING; memset( &item.header.bbox, 0, sizeof( item.header.bbox ) ); item.header.sphere.radius = 0; if ( !fOnlyNotingExistence && type == PIID_IPHYSICSOBJECT ) { // Don't doing the box thing for things like wheels on cars IPhysicsObject *pPhysObj = (IPhysicsObject *)(*ppPhysObj); if ( pPhysObj ) { item.header.modelName = GetModelName( pPhysObj ); item.header.iCollide = physcollision->CollideIndex( pPhysObj->GetCollide() ); if ( item.header.modelName == NULL_STRING ) { BBox_t *pBBox = GetBBox( pPhysObj ); if ( pBBox != NULL ) { item.header.bbox = *pBBox; } else { if ( pPhysObj && pPhysObj->GetSphereRadius() != 0 ) { item.header.sphere.radius = pPhysObj->GetSphereRadius(); } else { DevMsg( "Don't know how to save model for physics object (class \"%s\")\n", pOwner->GetClassname() ); } } } } } m_QueuedSaves.Insert( item ); }
//------------------------------------------------------------------------------ // Purpose : Initialize a gibs position and velocity // Input : // Output : //------------------------------------------------------------------------------ void CGib::InitGib( CBaseEntity *pVictim, float fMinVelocity, float fMaxVelocity ) { // ------------------------------------------------------------------------ // If have a pVictim spawn the gib somewhere in the pVictim's bounding volume // ------------------------------------------------------------------------ if ( pVictim ) { // Find a random position within the bounding box (add 1 to Z to get it out of the ground) Vector vecOrigin; pVictim->CollisionProp()->RandomPointInBounds( vec3_origin, Vector( 1, 1, 1 ), &vecOrigin ); vecOrigin.z += 1.0f; SetAbsOrigin( vecOrigin ); // make the gib fly away from the attack vector Vector vecNewVelocity = g_vecAttackDir * -1; // mix in some noise vecNewVelocity.x += random->RandomFloat ( -0.25, 0.25 ); vecNewVelocity.y += random->RandomFloat ( -0.25, 0.25 ); vecNewVelocity.z += random->RandomFloat ( -0.25, 0.25 ); vecNewVelocity *= random->RandomFloat ( fMaxVelocity, fMinVelocity ); QAngle vecNewAngularVelocity = GetLocalAngularVelocity(); vecNewAngularVelocity.x = random->RandomFloat ( 100, 200 ); vecNewAngularVelocity.y = random->RandomFloat ( 100, 300 ); SetLocalAngularVelocity( vecNewAngularVelocity ); // copy owner's blood color SetBloodColor( pVictim->BloodColor() ); AdjustVelocityBasedOnHealth( pVictim->m_iHealth, vecNewVelocity ); // Attempt to be physical if we can if ( VPhysicsInitNormal( SOLID_BBOX, 0, false ) ) { IPhysicsObject *pObj = VPhysicsGetObject(); if ( pObj != NULL ) { AngularImpulse angImpulse = RandomAngularImpulse( -500, 500 ); pObj->AddVelocity( &vecNewVelocity, &angImpulse ); } } else { SetSolid( SOLID_BBOX ); SetCollisionBounds( vec3_origin, vec3_origin ); SetAbsVelocity( vecNewVelocity ); } SetCollisionGroup( COLLISION_GROUP_DEBRIS ); } LimitVelocity(); }
static void SyncAnimatingWithPhysics( CBaseAnimating *pAnimating ) { IPhysicsObject *pPhysics = pAnimating->VPhysicsGetObject(); if ( pPhysics ) { Vector pos; pPhysics->GetShadowPosition( &pos, NULL ); pAnimating->SetAbsOrigin( pos ); } }
void CFuncWallToggle::TurnOn( void ) { IPhysicsObject *pPhys = VPhysicsGetObject(); if ( pPhys ) { pPhys->EnableCollisions( true ); } RemoveSolidFlags( FSOLID_NOT_SOLID ); RemoveEffects( EF_NODRAW ); }
void CFuncWallToggle::TurnOff( void ) { IPhysicsObject *pPhys = VPhysicsGetObject(); if ( pPhys ) { pPhys->EnableCollisions( false ); } AddSolidFlags( FSOLID_NOT_SOLID ); AddEffects( EF_NODRAW ); }
void CWeaponGravityGun::SoundUpdate( void ) { int newState; if ( m_hObject ) newState = SS_LOCKEDON; else newState = SS_SCANNING; if ( newState != m_soundState ) { SoundStop(); m_soundState = newState; SoundStart(); } switch( m_soundState ) { case SS_SCANNING: break; case SS_LOCKEDON: { CPASAttenuationFilter filter( this ); float height = m_hObject->GetAbsOrigin().z - m_originalObjectPosition.z; // go from pitch 90 to 150 over a height of 500 int pitch = 90 + (int)UTIL_LineFraction( height, 0, 500, 60 ); assert(m_sndLockedOn!=NULL); if ( m_sndLockedOn != NULL ) { (CSoundEnvelopeController::GetController()).SoundChangePitch( m_sndLockedOn, pitch, 0.0f ); } // attenutate the movement sounds over 200 units of movement float distance = UTIL_LineFraction( m_movementLength, 0, 200, 1.0 ); // blend the "mass" sounds between 50 and 500 kg IPhysicsObject *pPhys = GetPhysObjFromPhysicsBone( m_hObject, m_physicsBone ); if ( pPhys == NULL ) { // we no longer exist! break; } float fade = UTIL_LineFraction( pPhys->GetMass(), 50, 500, 1.0 ); (CSoundEnvelopeController::GetController()).SoundChangeVolume( m_sndLightObject, fade * distance, 0.0f ); (CSoundEnvelopeController::GetController()).SoundChangeVolume( m_sndHeavyObject, (1.0 - fade) * distance, 0.0f ); } break; } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CPhysicsCannister::CannisterActivate( CBaseEntity *pActivator, const Vector &thrustOffset ) { // already active or spent if ( m_active || !m_thrustTime ) { return; } m_hLauncher = pActivator; Vector thrustDirection = CalcLocalThrust( thrustOffset ); m_onActivate.FireOutput( pActivator, this, 0 ); m_thruster.CalcThrust( m_thrustOrigin, thrustDirection, VPhysicsGetObject() ); m_pController = physenv->CreateMotionController( &m_thruster ); IPhysicsObject *pPhys = VPhysicsGetObject(); m_pController->AttachObject( pPhys, true ); // Make sure the object is simulated pPhys->Wake(); m_active = true; m_activateTime = gpGlobals->curtime; SetNextThink( gpGlobals->curtime + m_thrustTime ); SetThink( &CPhysicsCannister::BeginShutdownThink ); QAngle angles; VectorAngles( -thrustDirection, angles ); m_pJet = dynamic_cast<CSteamJet *>( CBaseEntity::Create( "env_steam", m_thrustOrigin, angles, this ) ); m_pJet->SetParent( this ); float extra = m_thruster.m_thrust * (1/5000.f); extra = clamp( extra, 0, 1 ); m_pJet->m_SpreadSpeed = 15 * m_thruster.m_thrust * 0.001; m_pJet->m_Speed = 128 + 100 * extra; m_pJet->m_StartSize = 10; m_pJet->m_EndSize = 25; m_pJet->m_Rate = 52 + (int)extra*20; m_pJet->m_JetLength = 64; m_pJet->m_clrRender = m_clrRender; m_pJet->Use( this, this, USE_ON, 1 ); if ( m_gasSound != NULL_STRING ) { CPASAttenuationFilter filter( this ); EmitSound_t ep; ep.m_nChannel = CHAN_ITEM; ep.m_pSoundName = STRING(m_gasSound); ep.m_flVolume = 1.0f; ep.m_SoundLevel = SNDLVL_NORM; EmitSound( filter, entindex(), ep ); } }
//----------------------------------------------------------------------------- // Purpose: Returns the magnitude of the entity's angular velocity. //----------------------------------------------------------------------------- float CPointAngularVelocitySensor::SampleAngularVelocity(CBaseEntity *pEntity) { if (pEntity->GetMoveType() == MOVETYPE_VPHYSICS) { IPhysicsObject *pPhys = pEntity->VPhysicsGetObject(); if (pPhys != NULL) { Vector vecVelocity; AngularImpulse vecAngVelocity; pPhys->GetVelocity(&vecVelocity, &vecAngVelocity); QAngle angles; pPhys->GetPosition( NULL, &angles ); float dt = gpGlobals->curtime - GetLastThink(); if ( dt == 0 ) dt = 0.1; // HACKHACK: We don't expect a real 'delta' orientation here, just enough of an error estimate to tell if this thing // is trying to move, but failing. QAngle delta = angles - m_lastOrientation; if ( ( delta.Length() / dt ) < ( vecAngVelocity.Length() * 0.01 ) ) { return 0.0f; } m_lastOrientation = angles; if ( m_bUseHelper == false ) { return vecAngVelocity.Length(); } else { Vector vLine = m_vecAxis - GetAbsOrigin(); VectorNormalize( vLine ); Vector vecWorldAngVelocity; pPhys->LocalToWorldVector( &vecWorldAngVelocity, vecAngVelocity ); float flDot = DotProduct( vecWorldAngVelocity, vLine ); return flDot; } } } else { QAngle vecAngVel = pEntity->GetLocalAngularVelocity(); float flMax = MAX(fabs(vecAngVel[PITCH]), fabs(vecAngVel[YAW])); return MAX(flMax, fabs(vecAngVel[ROLL])); } return 0; }
void C_PhysPropClientside::Clone( Vector &velocity ) { C_PhysPropClientside *pEntity = C_PhysPropClientside::CreateNew(); if ( !pEntity ) return; pEntity->m_spawnflags = m_spawnflags; // We never want to be motion disabled pEntity->m_spawnflags &= ~SF_PHYSPROP_MOTIONDISABLED; pEntity->SetDmgModBullet( GetDmgModBullet() ); pEntity->SetDmgModClub( GetDmgModClub() ); pEntity->SetDmgModExplosive( GetDmgModExplosive() ); pEntity->SetModelName( GetModelName() ); pEntity->SetLocalOrigin( GetLocalOrigin() ); pEntity->SetLocalAngles( GetLocalAngles() ); pEntity->SetOwnerEntity( this ); pEntity->SetPhysicsMode( PHYSICS_MULTIPLAYER_CLIENTSIDE ); if ( !pEntity->Initialize() ) { pEntity->Release(); return; } pEntity->m_nSkin = m_nSkin; pEntity->m_iHealth = m_iHealth; if ( pEntity->m_iHealth == 0 ) { // if no health, don't collide with player anymore, don't take damage pEntity->m_takedamage = DAMAGE_NO; pEntity->SetCollisionGroup( COLLISION_GROUP_NONE ); } IPhysicsObject *pPhysicsObject = pEntity->VPhysicsGetObject(); if( pPhysicsObject ) { // randomize velocity by 5% float rndf = RandomFloat( -0.025, 0.025 ); Vector rndVel = velocity + rndf*velocity; pPhysicsObject->AddVelocity( &rndVel, NULL ); } else { // failed to create a physics object pEntity->Release(); } }