void CGravControllerPoint::DetachEntity( void ) { CBaseEntity *pEntity = m_attachedEntity; if ( pEntity ) { IPhysicsObject *pPhys = GetPhysObjFromPhysicsBone( pEntity, m_attachedPhysicsBone ); if ( pPhys ) { // on the odd chance that it's gone to sleep while under anti-gravity pPhys->Wake(); pPhys->SetDamping( NULL, &m_saveDamping ); pPhys->SetMass( m_saveMass ); } } m_attachedEntity = NULL; m_attachedPhysicsBone = 0; if ( physenv ) { physenv->DestroyMotionController( m_controller ); } m_controller = NULL; // UNDONE: Does this help the networking? m_targetPosition = vec3_origin; m_worldPosition = vec3_origin; }
bool CPushable::CreateVPhysics( void ) { VPhysicsInitNormal( SOLID_VPHYSICS, 0, false ); IPhysicsObject *pPhysObj = VPhysicsGetObject(); if ( pPhysObj ) { pPhysObj->SetMass( 30 ); // Vector vecInertia = Vector(800, 800, 800); // pPhysObj->SetInertia( vecInertia ); } return true; }
//----------------------------------------------------------------------------- // Purpose: Input handler for setting the breakable's mass. //----------------------------------------------------------------------------- void CBreakable::InputSetMass( inputdata_t &inputdata ) { IPhysicsObject * vPhys = VPhysicsGetObject(); if ( vPhys ) { float toMass = inputdata.value.Float(); Assert(toMass > 0); vPhys->SetMass( toMass ); } else { Warning( "Tried to call SetMass() on %s but it has no physics.\n", GetEntityName().ToCStr() ); } }
//----------------------------------------------------------------------------- // Purpose: Creates a dense ball with a mass equal to the aggregate mass consumed by the vortex //----------------------------------------------------------------------------- void CGravityVortexController::CreateDenseBall( void ) { CBaseEntity *pBall = CreateEntityByName( "prop_physics" ); pBall->SetModel( DENSE_BALL_MODEL ); pBall->SetAbsOrigin( GetAbsOrigin() ); pBall->Spawn(); IPhysicsObject *pObj = pBall->VPhysicsGetObject(); if ( pObj != NULL ) { pObj->SetMass( GetConsumedMass() ); } }
void CGrabController::DetachEntity( bool bClearVelocity ) { Assert(!PhysIsInCallback()); CBaseEntity *pEntity = GetAttached(); if ( pEntity ) { // Restore the LS blocking state pEntity->SetBlocksLOS( m_bCarriedEntityBlocksLOS ); IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; int count = pEntity->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); for ( int i = 0; i < count; i++ ) { IPhysicsObject *pPhys = pList[i]; if ( !pPhys ) continue; // on the odd chance that it's gone to sleep while under anti-gravity pPhys->EnableDrag( true ); pPhys->Wake(); pPhys->SetMass( m_savedMass[i] ); pPhys->SetDamping( NULL, &m_savedRotDamping[i] ); PhysClearGameFlags( pPhys, FVPHYSICS_PLAYER_HELD ); if ( bClearVelocity ) { PhysForceClearVelocity( pPhys ); } else { ClampPhysicsVelocity( pPhys, player_walkspeed.GetFloat() * 1.5f, 2.0f * 360.0f ); } } } m_attachedEntity = NULL; physenv->DestroyMotionController( m_controller ); m_controller = NULL; }
//Actual work code IterationRetval_t EnumElement( IHandleEntity *pHandleEntity ) { C_BaseEntity *pEnt = ClientEntityList().GetBaseEntityFromHandle( pHandleEntity->GetRefEHandle() ); if ( pEnt == NULL ) return ITERATION_CONTINUE; C_BaseAnimating *pModel = static_cast< C_BaseAnimating * >( pEnt ); if ( pModel == NULL ) return ITERATION_CONTINUE; trace_t tr; enginetrace->ClipRayToEntity( m_rayShot, MASK_SHOT, pModel, &tr ); IPhysicsObject *pPhysicsObject = NULL; //Find the real object we hit. if( tr.physicsbone >= 0 ) { if ( pModel->m_pRagdoll ) { CRagdoll *pCRagdoll = dynamic_cast < CRagdoll * > ( pModel->m_pRagdoll ); if ( pCRagdoll ) { ragdoll_t *pRagdollT = pCRagdoll->GetRagdoll(); if ( tr.physicsbone < pRagdollT->listCount ) { pPhysicsObject = pRagdollT->list[tr.physicsbone].pObject; } } } } if ( pPhysicsObject == NULL ) return ITERATION_CONTINUE; if ( tr.fraction < 1.0 ) { IPhysicsObject *pReference = GetWorldPhysObject(); if ( pReference == NULL || pPhysicsObject == NULL ) return ITERATION_CONTINUE; float flMass = pPhysicsObject->GetMass(); pPhysicsObject->SetMass( flMass * 2 ); constraint_ballsocketparams_t ballsocket; ballsocket.Defaults(); pReference->WorldToLocal( &ballsocket.constraintPosition[0], m_vWorld ); pPhysicsObject->WorldToLocal( &ballsocket.constraintPosition[1], tr.endpos ); physenv->CreateBallsocketConstraint( pReference, pPhysicsObject, NULL, ballsocket ); //Play a sound CPASAttenuationFilter filter( pEnt ); EmitSound_t ep; ep.m_nChannel = CHAN_VOICE; ep.m_pSoundName = "Weapon_Crossbow.BoltSkewer"; ep.m_flVolume = 1.0f; ep.m_SoundLevel = SNDLVL_NORM; ep.m_pOrigin = &pEnt->GetAbsOrigin(); C_BaseEntity::EmitSound( filter, SOUND_FROM_WORLD, ep ); return ITERATION_STOP; } return ITERATION_CONTINUE; }
//----------------------------------------------------------------------------- // Purpose: // Input : *pOther - //----------------------------------------------------------------------------- void CGrappleHook::HookTouch(CBaseEntity *pOther) { if (!pOther->IsSolid() || pOther->IsSolidFlagSet(FSOLID_VOLUME_CONTENTS)) return; if ((pOther != m_hOwner) && (pOther->m_takedamage != DAMAGE_NO)) { m_hOwner->NotifyHookDied(); SetTouch(NULL); SetThink(NULL); UTIL_Remove(this); } else { trace_t tr; tr = BaseClass::GetTouchTrace(); // See if we struck the world if (pOther->GetMoveType() == MOVETYPE_NONE && !(tr.surface.flags & SURF_SKY)) { EmitSound("Weapon_AR2.Reload_Push"); // if what we hit is static architecture, can stay around for a while. Vector vecDir = GetAbsVelocity(); //FIXME: We actually want to stick (with hierarchy) to what we've hit SetMoveType(MOVETYPE_NONE); Vector vForward; AngleVectors(GetAbsAngles(), &vForward); VectorNormalize(vForward); CEffectData data; data.m_vOrigin = tr.endpos; data.m_vNormal = vForward; data.m_nEntIndex = 0; // DispatchEffect( "Impact", data ); // AddEffects( EF_NODRAW ); SetTouch(NULL); VPhysicsDestroyObject(); VPhysicsInitNormal(SOLID_VPHYSICS, FSOLID_NOT_STANDABLE, false); AddSolidFlags(FSOLID_NOT_SOLID); // SetMoveType( MOVETYPE_NONE ); if (!m_hPlayer) { Assert(0); return; } // Set Jay's gai flag m_hPlayer->SetPhysicsFlag(PFLAG_VPHYSICS_MOTIONCONTROLLER, true); //IPhysicsObject *pPhysObject = m_hPlayer->VPhysicsGetObject(); IPhysicsObject *pRootPhysObject = VPhysicsGetObject(); Assert(pRootPhysObject); //Assert(pPhysObject); pRootPhysObject->EnableMotion(false); // Root has huge mass, tip has little pRootPhysObject->SetMass(VPHYSICS_MAX_MASS); // pPhysObject->SetMass( 100 ); // float damping = 3; // pPhysObject->SetDamping( &damping, &damping ); Vector origin = m_hPlayer->GetAbsOrigin(); Vector rootOrigin = GetAbsOrigin(); m_fSpringLength = (origin - rootOrigin).Length(); m_bPlayerWasStanding = ((m_hPlayer->GetFlags() & FL_DUCKING) == 0); SetThink(&CGrappleHook::HookedThink); SetNextThink(gpGlobals->curtime + 0.1f); } else { // Put a mark unless we've hit the sky if ((tr.surface.flags & SURF_SKY) == false) { UTIL_ImpactTrace(&tr, DMG_BULLET); } SetTouch(NULL); SetThink(NULL); m_hOwner->NotifyHookDied(); UTIL_Remove(this); } } }
bool CStatueProp::CreateVPhysicsFromOBBs( CBaseAnimating *pInitBaseAnimating ) { // Make enough pointers to convexes for each hitbox CPhysConvex **ppConvex = new (CPhysConvex*[ m_pInitOBBs->Count() ]); float flTotalVolume = 0.0f; float flTotalSurfaceArea = 0.0f; for ( int i = 0; i < m_pInitOBBs->Count(); i++ ) { const outer_collision_obb_t *pOBB = &((*m_pInitOBBs)[ i ]); // Accumulate volume and area Vector flDimentions = pOBB->vecMaxs - pOBB->vecMins; flTotalVolume += flDimentions.x * flDimentions.y * flDimentions.z; flTotalSurfaceArea += 2.0f * ( flDimentions.x * flDimentions.y + flDimentions.x * flDimentions.z + flDimentions.y * flDimentions.z ); // Get angled min and max extents Vector vecMins, vecMaxs; VectorRotate( pOBB->vecMins, pOBB->angAngles, vecMins ); VectorRotate( pOBB->vecMaxs, pOBB->angAngles, vecMaxs ); // Get the corners in world space Vector vecMinCorner = pOBB->vecPos + vecMins; Vector vecMaxCorner = pOBB->vecPos + vecMaxs; // Get the normals of the hitbox in world space Vector vecForward, vecRight, vecUp; AngleVectors( pOBB->angAngles, &vecForward, &vecRight, &vecUp ); vecRight = -vecRight; // Convert corners and normals to local space Vector vecCornerLocal[ 2 ]; Vector vecNormalLocal[ 3 ]; matrix3x4_t matToWorld = EntityToWorldTransform(); VectorITransform( vecMaxCorner, matToWorld, vecCornerLocal[ 0 ] ); VectorITransform( vecMinCorner, matToWorld, vecCornerLocal[ 1 ] ); VectorIRotate( vecForward, matToWorld, vecNormalLocal[ 0 ] ); VectorIRotate( vecRight, matToWorld, vecNormalLocal[ 1 ] ); VectorIRotate( vecUp, matToWorld, vecNormalLocal[ 2 ] ); // Create 6 planes from the local oriented hit box data float pPlanes[ 4 * 6 ]; for ( int iPlane = 0; iPlane < 6; ++iPlane ) { int iPlaneMod2 = iPlane % 2; int iPlaneDiv2 = iPlane / 2; bool bOdd = ( iPlaneMod2 == 1 ); // Plane Normal pPlanes[ iPlane * 4 + 0 ] = vecNormalLocal[ iPlaneDiv2 ].x * ( bOdd ? -1.0f : 1.0f ); pPlanes[ iPlane * 4 + 1 ] = vecNormalLocal[ iPlaneDiv2 ].y * ( bOdd ? -1.0f : 1.0f ); pPlanes[ iPlane * 4 + 2 ] = vecNormalLocal[ iPlaneDiv2 ].z * ( bOdd ? -1.0f : 1.0f ); // Plane D pPlanes[ iPlane * 4 + 3 ] = ( vecCornerLocal[ iPlaneMod2 ].x * vecNormalLocal[ iPlaneDiv2 ].x + vecCornerLocal[ iPlaneMod2 ].y * vecNormalLocal[ iPlaneDiv2 ].y + vecCornerLocal[ iPlaneMod2 ].z * vecNormalLocal[ iPlaneDiv2 ].z ) * ( bOdd ? -1.0f : 1.0f ); } // Create convex from the intersection of these planes ppConvex[ i ] = physcollision->ConvexFromPlanes( pPlanes, 6, 0.0f ); } // Make a single collide out of the group of convex boxes CPhysCollide *pPhysCollide = physcollision->ConvertConvexToCollide( ppConvex, m_pInitOBBs->Count() ); delete[] ppConvex; // Create the physics object objectparams_t params = g_PhysDefaultObjectParams; params.pGameData = static_cast<void *>( this ); int nMaterialIndex = physprops->GetSurfaceIndex( "ice" ); // use ice material IPhysicsObject* p = physenv->CreatePolyObject( pPhysCollide, nMaterialIndex, GetAbsOrigin(), GetAbsAngles(), ¶ms ); Assert( p != NULL ); // Set velocity Vector vecInitialVelocity = pInitBaseAnimating->GetAbsVelocity(); p->SetVelocity( &vecInitialVelocity, NULL ); // Compute mass float flMass; float flDensity, flThickness; physprops->GetPhysicsProperties( nMaterialIndex, &flDensity, &flThickness, NULL, NULL ); // Make it more hollow flThickness = MIN ( 1.0f, flThickness + 0.5f ); if ( flThickness > 0.0f ) { flMass = flTotalSurfaceArea * flThickness * CUBIC_METERS_PER_CUBIC_INCH * flDensity; } else { // density is in kg/m^3, volume is in in^3 flMass = flTotalVolume * CUBIC_METERS_PER_CUBIC_INCH * flDensity; } // Mass is somewhere between the original and if it was all ice p->SetMass( flMass ); // Yes, gravity p->EnableGravity( true ); // Use this as our vphysics VPhysicsSetObject( p ); SetSolid( SOLID_VPHYSICS ); AddSolidFlags( FSOLID_CUSTOMRAYTEST | FSOLID_CUSTOMBOXTEST ); SetMoveType( MOVETYPE_VPHYSICS ); m_pInitOBBs = NULL; return true; }
bool CStatueProp::CreateVPhysicsFromHitBoxes( CBaseAnimating *pInitBaseAnimating ) { if ( !pInitBaseAnimating ) return false; // Use the current animation sequence and cycle CopyAnimationDataFrom( pInitBaseAnimating ); // Copy over any render color color24 colorRender = pInitBaseAnimating->GetRenderColor(); SetRenderColor( colorRender.r, colorRender.g, colorRender.b ); SetRenderAlpha( pInitBaseAnimating->GetRenderAlpha() ); // Get hitbox data CStudioHdr *pStudioHdr = GetModelPtr(); if ( !pStudioHdr ) return false; mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( m_nHitboxSet ); if ( !set ) return false; Vector position; QAngle angles; // Make enough pointers to convexes for each hitbox CPhysConvex **ppConvex = new (CPhysConvex*[ set->numhitboxes ]); float flTotalVolume = 0.0f; float flTotalSurfaceArea = 0.0f; for ( int i = 0; i < set->numhitboxes; i++ ) { // Get the hitbox info mstudiobbox_t *pbox = set->pHitbox( i ); GetBonePosition( pbox->bone, position, angles ); // Accumulate volume and area Vector flDimentions = pbox->bbmax - pbox->bbmin; flTotalVolume += flDimentions.x * flDimentions.y * flDimentions.z; flTotalSurfaceArea += 2.0f * ( flDimentions.x * flDimentions.y + flDimentions.x * flDimentions.z + flDimentions.y * flDimentions.z ); // Get angled min and max extents Vector vecMins, vecMaxs; VectorRotate( pbox->bbmin, angles, vecMins ); VectorRotate( pbox->bbmax, angles, vecMaxs ); // Get the corners in world space Vector vecMinCorner = position + vecMins; Vector vecMaxCorner = position + vecMaxs; // Get the normals of the hitbox in world space Vector vecForward, vecRight, vecUp; AngleVectors( angles, &vecForward, &vecRight, &vecUp ); vecRight = -vecRight; // Convert corners and normals to local space Vector vecCornerLocal[ 2 ]; Vector vecNormalLocal[ 3 ]; matrix3x4_t matToWorld = EntityToWorldTransform(); VectorITransform( vecMaxCorner, matToWorld, vecCornerLocal[ 0 ] ); VectorITransform( vecMinCorner, matToWorld, vecCornerLocal[ 1 ] ); VectorIRotate( vecForward, matToWorld, vecNormalLocal[ 0 ] ); VectorIRotate( vecRight, matToWorld, vecNormalLocal[ 1 ] ); VectorIRotate( vecUp, matToWorld, vecNormalLocal[ 2 ] ); // Create 6 planes from the local oriented hit box data float pPlanes[ 4 * 6 ]; for ( int iPlane = 0; iPlane < 6; ++iPlane ) { int iPlaneMod2 = iPlane % 2; int iPlaneDiv2 = iPlane / 2; bool bOdd = ( iPlaneMod2 == 1 ); // Plane Normal pPlanes[ iPlane * 4 + 0 ] = vecNormalLocal[ iPlaneDiv2 ].x * ( bOdd ? -1.0f : 1.0f ); pPlanes[ iPlane * 4 + 1 ] = vecNormalLocal[ iPlaneDiv2 ].y * ( bOdd ? -1.0f : 1.0f ); pPlanes[ iPlane * 4 + 2 ] = vecNormalLocal[ iPlaneDiv2 ].z * ( bOdd ? -1.0f : 1.0f ); // Plane D pPlanes[ iPlane * 4 + 3 ] = ( vecCornerLocal[ iPlaneMod2 ].x * vecNormalLocal[ iPlaneDiv2 ].x + vecCornerLocal[ iPlaneMod2 ].y * vecNormalLocal[ iPlaneDiv2 ].y + vecCornerLocal[ iPlaneMod2 ].z * vecNormalLocal[ iPlaneDiv2 ].z ) * ( bOdd ? -1.0f : 1.0f ); } // Create convex from the intersection of these planes ppConvex[ i ] = physcollision->ConvexFromPlanes( pPlanes, 6, 0.0f ); } // Make a single collide out of the group of convex boxes CPhysCollide *pPhysCollide = physcollision->ConvertConvexToCollide( ppConvex, set->numhitboxes ); delete[] ppConvex; // Create the physics object objectparams_t params = g_PhysDefaultObjectParams; params.pGameData = static_cast<void *>( this ); int nMaterialIndex = physprops->GetSurfaceIndex( "ice" ); // use ice material IPhysicsObject* p = physenv->CreatePolyObject( pPhysCollide, nMaterialIndex, GetAbsOrigin(), GetAbsAngles(), ¶ms ); Assert( p != NULL ); // Set velocity Vector vecInitialVelocity = pInitBaseAnimating->GetAbsVelocity(); p->SetVelocity( &vecInitialVelocity, NULL ); // Compute mass float flMass; float flDensity, flThickness; physprops->GetPhysicsProperties( nMaterialIndex, &flDensity, &flThickness, NULL, NULL ); // Make it more hollow flThickness = MIN ( 1.0f, flThickness + 0.5f ); if ( flThickness > 0.0f ) { flMass = flTotalSurfaceArea * flThickness * CUBIC_METERS_PER_CUBIC_INCH * flDensity; } else { // density is in kg/m^3, volume is in in^3 flMass = flTotalVolume * CUBIC_METERS_PER_CUBIC_INCH * flDensity; } // Mass is somewhere between the original and if it was all ice p->SetMass( flMass ); // Yes, gravity p->EnableGravity( true ); // Use this as our vphysics VPhysicsSetObject( p ); SetSolid( SOLID_VPHYSICS ); AddSolidFlags( FSOLID_CUSTOMRAYTEST | FSOLID_CUSTOMBOXTEST ); SetMoveType( MOVETYPE_VPHYSICS ); if ( pInitBaseAnimating != this ) { // Transfer children from the init base animating TransferChildren( pInitBaseAnimating, this ); CBaseEntity *pChild = FirstMoveChild(); while ( pChild ) { CEntityFreezing *pFreezing = dynamic_cast<CEntityFreezing*>( pChild ); if ( pFreezing ) { pFreezing->FinishFreezing(); } pChild = pChild->NextMovePeer(); } } return true; }