void RagdollActivate( ragdoll_t &ragdoll, vcollide_t *pCollide, int modelIndex, bool bForceWake ) { RagdollSetupCollisions( ragdoll, pCollide, modelIndex ); for ( int i = 0; i < ragdoll.listCount; i++ ) { ragdoll.list[i].pObject->SetGameIndex( i ); PhysSetGameFlags( ragdoll.list[i].pObject, FVPHYSICS_MULTIOBJECT_ENTITY ); // now that the relationships are set, activate the collision system ragdoll.list[i].pObject->EnableCollisions( true ); if ( bForceWake == true ) { ragdoll.list[i].pObject->Wake(); } } if ( ragdoll.pGroup ) { // NOTE: This also wakes the objects ragdoll.pGroup->Activate(); // so if we didn't want that, we'll need to put them back to sleep here if ( !bForceWake ) { for ( int i = 0; i < ragdoll.listCount; i++ ) { ragdoll.list[i].pObject->Sleep(); } } } }
bool CTripmineGrenade::MakeConstraint( CBaseEntity *pObject ) { IPhysicsObject *cMinePhysics = VPhysicsGetObject(); Assert( cMinePhysics ); IPhysicsObject *pAttached = pObject->VPhysicsGetObject(); if ( !cMinePhysics || !pAttached ) return false; // constraining to the world means object 1 is fixed if ( pAttached == g_PhysWorldObject ) PhysSetGameFlags( cMinePhysics, FVPHYSICS_CONSTRAINT_STATIC ); IPhysicsConstraintGroup *pGroup = NULL; constraint_fixedparams_t fixed; fixed.Defaults(); fixed.InitWithCurrentObjectState( cMinePhysics, pAttached ); fixed.constraint.Defaults(); m_pConstraint = physenv->CreateFixedConstraint( cMinePhysics, pAttached, pGroup, fixed ); if (!m_pConstraint) return false; m_pConstraint->SetGameData( (void *)this ); return true; }
//--------------------------------------------------------- //--------------------------------------------------------- void CBounceBomb::CloseHooks() { if( !m_bLockSilently ) { EmitSound( "NPC_CombineMine.CloseHooks" ); } if( VPhysicsGetObject() ) { // It's possible to not have a valid physics object here, since this function doubles as an initialization function. PhysSetGameFlags( VPhysicsGetObject(), FVPHYSICS_CONSTRAINT_STATIC ); } // Only lock silently the first time we call this. m_bLockSilently = false; SetPoseParameter( m_iAllHooks, 0 ); VPhysicsGetObject()->EnableMotion( false ); // Once I lock down, forget how many tries it took. m_iFlipAttempts = 0; #ifdef _XBOX AddEffects( EF_NOSHADOW ); #endif }
CBaseEntity *CreateCombineBall( const Vector &origin, const Vector &velocity, float radius, float mass, float lifetime, CBaseEntity *pOwner ) { if(_CreateCombineBall != NULL) { CBaseEntity *pReturn = NULL; pReturn = _CreateCombineBall(origin, velocity, radius, mass, lifetime, pOwner); // If the radius is greater than the max, let's do some hacks to make it work if ( radius > 12.0f ) { VFuncs::SetCombineBallRadius( pReturn, radius ); // After changing the radius, we need to recreate the VPhysics object VFuncs::VPhysicsDestroyObject( pReturn ); VFuncs::CreateVPhysics( pReturn ); // We need to set the same things on the new physics object that Spawn and CreateCombineBall set VFuncs::VPhysicsGetObject( pReturn )->SetVelocity( &velocity, NULL ); PhysSetGameFlags( VFuncs::VPhysicsGetObject( pReturn ), FVPHYSICS_WAS_THROWN ); } return pReturn; } return NULL; }
void CWeaponGravityGun::AttachObject( CBaseEntity *pObject, const Vector& start, const Vector &end, float distance ) { CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); if( !pOwner ) return; m_hObject = pObject; m_useDown = false; IPhysicsObject *pPhysics = pObject ? (pObject->VPhysicsGetObject()) : NULL; if ( pPhysics && pObject->GetMoveType() == MOVETYPE_VPHYSICS ) { m_distance = distance; Vector worldPosition; pObject->WorldToEntitySpace( end, &worldPosition ); m_worldPosition = worldPosition; m_gravCallback.AttachEntity( pOwner, pObject, pPhysics, pObject->GetAbsOrigin() ); m_originalObjectPosition = pObject->GetAbsOrigin(); pPhysics->Wake(); PhysSetGameFlags( pPhysics, FVPHYSICS_PLAYER_HELD ); #ifndef CLIENT_DLL Pickup_OnPhysGunPickup( pObject, pOwner ); #endif } else { m_hObject = NULL; } }
bool CPhysBox::CreateVPhysics() { solid_t tmpSolid; PhysModelParseSolid( tmpSolid, this, GetModelIndex() ); if ( m_massScale > 0 ) { float mass = tmpSolid.params.mass * m_massScale; mass = clamp( mass, 0.5, 1e6 ); tmpSolid.params.mass = mass; } PhysSolidOverride( tmpSolid, m_iszOverrideScript ); IPhysicsObject *pPhysics = VPhysicsInitNormal( GetSolid(), GetSolidFlags(), true, &tmpSolid ); if ( m_damageType == 1 ) { PhysSetGameFlags( pPhysics, FVPHYSICS_DMG_SLICE ); } // Wake it up if not asleep if ( !HasSpawnFlags(SF_PHYSBOX_ASLEEP) ) { VPhysicsGetObject()->Wake(); } if ( HasSpawnFlags(SF_PHYSBOX_MOTIONDISABLED) || m_damageToEnableMotion > 0 ) { VPhysicsGetObject()->EnableMotion( false ); } // only send data when physics moves this object NetworkStateManualMode( true ); return true; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CRagdollProp::OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ) { CDefaultPlayerPickupVPhysics::OnPhysGunDrop( pPhysGunUser, Reason ); m_hPhysicsAttacker = pPhysGunUser; m_flLastPhysicsInfluenceTime = gpGlobals->curtime; if( HasPhysgunInteraction( "onpickup", "boogie" ) ) { CRagdollBoogie::Create( this, 150, gpGlobals->curtime, 3.0f, SF_RAGDOLL_BOOGIE_ELECTRICAL ); } if ( HasSpawnFlags( SF_RAGDOLLPROP_USE_LRU_RETIREMENT ) ) { s_RagdollLRU.MoveToTopOfLRU( this ); } // Make sure it's interactive debris for at most 5 seconds if ( GetCollisionGroup() == COLLISION_GROUP_INTERACTIVE_DEBRIS ) { SetContextThink( &CRagdollProp::SetDebrisThink, gpGlobals->curtime + 5, s_pDebrisContext ); } if ( Reason != LAUNCHED_BY_CANNON ) return; if( HasPhysgunInteraction( "onlaunch", "spin_zaxis" ) ) { Vector vecAverageCenter( 0, 0, 0 ); // Get the average position, apply forces to produce a spin int j; ragdoll_t *pRagdollPhys = GetRagdoll( ); for ( j = 0; j < pRagdollPhys->listCount; ++j ) { Vector vecCenter; pRagdollPhys->list[j].pObject->GetPosition( &vecCenter, NULL ); vecAverageCenter += vecCenter; } vecAverageCenter /= pRagdollPhys->listCount; Vector vecZAxis( 0, 0, 1 ); for ( j = 0; j < pRagdollPhys->listCount; ++j ) { Vector vecDelta; pRagdollPhys->list[j].pObject->GetPosition( &vecDelta, NULL ); vecDelta -= vecAverageCenter; Vector vecDir; CrossProduct( vecZAxis, vecDelta, vecDir ); vecDir *= 100; pRagdollPhys->list[j].pObject->AddVelocity( &vecDir, NULL ); } } PhysSetGameFlags( VPhysicsGetObject(), FVPHYSICS_WAS_THROWN ); m_bFirstCollisionAfterLaunch = true; }
bool RagdollCreate( ragdoll_t &ragdoll, const ragdollparams_t ¶ms, IPhysicsEnvironment *pPhysEnv ) { RagdollCreateObjects( pPhysEnv, ragdoll, params ); if ( !ragdoll.listCount ) return false; int forceBone = params.forceBoneIndex; int i; float totalMass = 0; for ( i = 0; i < ragdoll.listCount; i++ ) { totalMass += ragdoll.list[i].pObject->GetMass(); } totalMass = max(totalMass,1); // apply force to the model Vector nudgeForce = params.forceVector; Vector forcePosition = params.forcePosition; // UNDONE: Test scaling the force by total mass on all bones Assert( forceBone < ragdoll.listCount ); if ( forceBone >= 0 && forceBone < ragdoll.listCount ) { ragdoll.list[forceBone].pObject->ApplyForceCenter( nudgeForce ); //nudgeForce *= 0.5; ragdoll.list[forceBone].pObject->GetPosition( &forcePosition, NULL ); } for ( i = 0; i < ragdoll.listCount; i++ ) { PhysSetGameFlags( ragdoll.list[i].pObject, FVPHYSICS_PART_OF_RAGDOLL ); } if ( forcePosition != vec3_origin ) { for ( i = 0; i < ragdoll.listCount; i++ ) { if ( forceBone != i ) { float scale = ragdoll.list[i].pObject->GetMass() / totalMass; ragdoll.list[i].pObject->ApplyForceOffset( scale * nudgeForce, forcePosition ); } } } return true; }
void CGrabController::AttachEntity( CBaseEntity *pEntity, IPhysicsObject *pPhys, const Vector &position, const QAngle &rotation ) { pPhys->GetDamping( NULL, &m_saveRotDamping ); float damping = 10; pPhys->SetDamping( NULL, &damping ); m_controller = physenv->CreateMotionController( this ); m_controller->AttachObject( pPhys ); m_controller->SetPriority( IPhysicsMotionController::HIGH_PRIORITY ); pPhys->Wake(); PhysSetGameFlags( pPhys, FVPHYSICS_PLAYER_HELD ); SetTargetPosition( position, rotation ); m_attachedEntity = pEntity; m_flLoadWeight = pPhys->GetMass(); }
bool RagdollCreate( ragdoll_t &ragdoll, const ragdollparams_t ¶ms, IPhysicsCollision *pPhysCollision, IPhysicsEnvironment *pPhysEnv, IPhysicsSurfaceProps *pSurfaceDatabase ) { RagdollCreateObjects( pPhysCollision, pPhysEnv, pSurfaceDatabase, ragdoll, params ); if ( !ragdoll.listCount ) return false; int forceBone = params.forceBoneIndex; int i; float totalMass = 0; for ( i = 0; i < ragdoll.listCount; i++ ) { totalMass += ragdoll.list[i].pObject->GetMass(); } totalMass = max(totalMass,1); // distribute half to the forced bone, half to the rest of the model Vector nudgeForce = params.forceVector; if ( forceBone >= 0 && forceBone <= ragdoll.listCount ) { nudgeForce *= 0.5; ragdoll.list[forceBone].pObject->ApplyForceCenter( nudgeForce ); } else if ( params.forcePosition != vec3_origin ) { for ( i = 0; i < ragdoll.listCount; i++ ) { float scale = ragdoll.list[i].pObject->GetMass() / totalMass; ragdoll.list[i].pObject->ApplyForceOffset( scale * nudgeForce, params.forcePosition ); } nudgeForce.Init(); } RagdollApplyAnimationAsVelocity( ragdoll, params.pPrevBones, params.pCurrentBones, params.boneDt ); for ( i = 0; i < ragdoll.listCount; i++ ) { float scale = ragdoll.list[i].pObject->GetMass() / totalMass; ragdoll.list[i].pObject->ApplyForceCenter( scale * nudgeForce ); PhysSetGameFlags( ragdoll.list[i].pObject, FVPHYSICS_PART_OF_RAGDOLL ); } return true; }
static void RagdollAddSolids( IPhysicsEnvironment *pPhysEnv, ragdoll_t &ragdoll, const ragdollparams_t ¶ms, cache_ragdollsolid_t *pSolids, int solidCount, const cache_ragdollconstraint_t *pConstraints, int constraintCount ) { const char *pszName = params.pStudioHdr->pszName(); Vector position; matrix3x4_t xform; // init parent index for ( int i = 0; i < solidCount; i++ ) { ragdoll.list[i].parentIndex = -1; } // now set from constraints for ( int i = 0; i < constraintCount; i++ ) { // save parent index ragdoll.list[pConstraints[i].childIndex].parentIndex = pConstraints[i].parentIndex; MatrixGetColumn( pConstraints[i].constraintToAttached, 3, ragdoll.list[pConstraints[i].childIndex].originParentSpace ); } // now setup the solids, using parent indices for ( int i = 0; i < solidCount; i++ ) { ragdoll.boneIndex[i] = pSolids[i].boneIndex; pSolids[i].params.pName = pszName; pSolids[i].params.pGameData = params.pGameData; ragdoll.list[i].pObject = pPhysEnv->CreatePolyObject( params.pCollide->solids[pSolids[i].collideIndex], pSolids[i].surfacePropIndex, vec3_origin, vec3_angle, &pSolids[i].params ); ragdoll.list[i].pObject->SetGameIndex( i ); int parentIndex = ragdoll.list[i].parentIndex; MatrixCopy( params.pCurrentBones[ragdoll.boneIndex[i]], xform ); if ( parentIndex >= 0 ) { Assert(parentIndex<i); ragdoll.list[parentIndex].pObject->LocalToWorld( &position, ragdoll.list[i].originParentSpace ); MatrixSetColumn( position, 3, xform ); } ragdoll.list[i].pObject->SetPositionMatrix( xform, true ); PhysSetGameFlags( ragdoll.list[i].pObject, FVPHYSICS_PART_OF_RAGDOLL ); } ragdoll.listCount = solidCount; }
void CWeaponGravityGun::AttachObject( CBaseEntity *pObject, IPhysicsObject *pPhysics, short physicsbone, const Vector& start, const Vector &end, float distance ) { CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); if( !pOwner ) return; m_hObject = pObject; m_physicsBone = physicsbone; m_useDown = false; if ( pPhysics && pObject->GetMoveType() == MOVETYPE_VPHYSICS ) { m_distance = distance; Vector worldPosition; pPhysics->WorldToLocal( &worldPosition, end ); m_worldPosition = worldPosition; Vector vecOrigin; pPhysics->GetPosition( &vecOrigin, NULL ); m_gravCallback.AttachEntity( pOwner, pObject, pPhysics, physicsbone, vecOrigin ); m_originalObjectPosition = vecOrigin; pPhysics->Wake(); IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; int count = pObject->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); for ( int i = 0; i < count; i++ ) { PhysSetGameFlags( pList[i], FVPHYSICS_PLAYER_HELD ); } #ifndef CLIENT_DLL Pickup_OnPhysGunPickup( pObject, pOwner ); #endif } else { m_hObject = NULL; m_physicsBone = 0; } }
//----------------------------------------------------------------------------- // Purpose: Initializes the vehicle physics // Called by our outer vehicle in it's Spawn() //----------------------------------------------------------------------------- bool CFourWheelVehiclePhysics::Initialize( const char *pVehicleScript, unsigned int nVehicleType ) { // Ok, turn on the simulation now // FIXME: Disabling collisions here is necessary because we seem to be // getting a one-frame collision between the old + new collision models if ( m_pOuter->VPhysicsGetObject() ) { m_pOuter->VPhysicsGetObject()->EnableCollisions(false); } m_pOuter->VPhysicsDestroyObject(); // Create the vphysics model + teleport it into position solid_t solid; vehicleparams_t vehicle; if (!ParseVehicleScript( pVehicleScript, solid, vehicle )) { UTIL_Remove(m_pOuter); return false; } // NOTE: this needs to be greater than your max framerate (so zero is still instant) m_throttleRate = 10000.0; if ( vehicle.engine.throttleTime > 0 ) { m_throttleRate = 1.0 / vehicle.engine.throttleTime; } m_flMaxSpeed = vehicle.engine.maxSpeed; IPhysicsObject *pBody = m_pOuter->VPhysicsInitNormal( SOLID_VPHYSICS, 0, false, &solid ); PhysSetGameFlags( pBody, FVPHYSICS_NO_SELF_COLLISIONS | FVPHYSICS_MULTIOBJECT_ENTITY ); m_pVehicle = physenv->CreateVehicleController( pBody, vehicle, nVehicleType, physgametrace ); m_wheelCount = m_pVehicle->GetWheelCount(); for ( int i = 0; i < m_wheelCount; i++ ) { m_pWheels[i] = m_pVehicle->GetWheel( i ); } return true; }
void CGrabController::AttachEntity( CBasePlayer *pPlayer, CBaseEntity *pEntity, IPhysicsObject *pPhys, bool bIsMegaPhysCannon, const Vector &vGrabPosition, bool bUseGrabPosition ) { // play the impact sound of the object hitting the player // used as feedback to let the player know he picked up the object int hitMaterial = pPhys->GetMaterialIndex(); int playerMaterial = pPlayer->VPhysicsGetObject() ? pPlayer->VPhysicsGetObject()->GetMaterialIndex() : hitMaterial; PhysicsImpactSound( pPlayer, pPhys, CHAN_STATIC, hitMaterial, playerMaterial, 1.0, 64 ); Vector position; QAngle angles; pPhys->GetPosition( &position, &angles ); // If it has a preferred orientation, use that instead. Pickup_GetPreferredCarryAngles( pEntity, pPlayer, pPlayer->EntityToWorldTransform(), angles ); // ComputeMaxSpeed( pEntity, pPhys ); // If we haven't been killed by a grab, we allow the gun to grab the nearest part of a ragdoll if ( bUseGrabPosition ) { IPhysicsObject *pChild = GetRagdollChildAtPosition( pEntity, vGrabPosition ); if ( pChild ) { pPhys = pChild; } } // Carried entities can never block LOS m_bCarriedEntityBlocksLOS = pEntity->BlocksLOS(); pEntity->SetBlocksLOS( false ); m_controller = physenv->CreateMotionController( this ); m_controller->AttachObject( pPhys, true ); // Don't do this, it's causing trouble with constraint solvers. //m_controller->SetPriority( IPhysicsMotionController::HIGH_PRIORITY ); pPhys->Wake(); PhysSetGameFlags( pPhys, FVPHYSICS_PLAYER_HELD ); SetTargetPosition( position, angles ); m_attachedEntity = pEntity; IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; int count = pEntity->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); m_flLoadWeight = 0; float damping = 10; float flFactor = count / 7.5f; if ( flFactor < 1.0f ) { flFactor = 1.0f; } for ( int i = 0; i < count; i++ ) { float mass = pList[i]->GetMass(); pList[i]->GetDamping( NULL, &m_savedRotDamping[i] ); m_flLoadWeight += mass; m_savedMass[i] = mass; // reduce the mass to prevent the player from adding crazy amounts of energy to the system pList[i]->SetMass( REDUCED_CARRY_MASS / flFactor ); pList[i]->SetDamping( NULL, &damping ); } // Give extra mass to the phys object we're actually picking up pPhys->SetMass( REDUCED_CARRY_MASS ); pPhys->EnableDrag( false ); m_errorTime = bIsMegaPhysCannon ? -1.5f : -1.0f; // 1 seconds until error starts accumulating m_error = 0; m_contactAmount = 0; m_attachedAnglesPlayerSpace = TransformAnglesToPlayerSpace( angles, pPlayer ); if ( m_angleAlignment != 0 ) { m_attachedAnglesPlayerSpace = AlignAngles( m_attachedAnglesPlayerSpace, m_angleAlignment ); } // Ragdolls don't offset this way if ( dynamic_cast<CRagdollProp*>(pEntity) ) { m_attachedPositionObjectSpace.Init(); } else { VectorITransform( pEntity->WorldSpaceCenter(), pEntity->EntityToWorldTransform(), m_attachedPositionObjectSpace ); } // If it's a prop, see if it has desired carry angles CPhysicsProp *pProp = dynamic_cast<CPhysicsProp *>(pEntity); if ( pProp ) { m_bHasPreferredCarryAngles = pProp->GetPropDataAngles( "preferred_carryangles", m_vecPreferredCarryAngles ); m_flDistanceOffset = pProp->GetCarryDistanceOffset(); } else { m_bHasPreferredCarryAngles = false; m_flDistanceOffset = 0; } m_bAllowObjectOverhead = IsObjectAllowedOverhead( pEntity ); }