//----------------------------------------------------------------------------- // Purpose: // Input : *pPlayer - // *pObject - //----------------------------------------------------------------------------- void CPlayerPickupController::Init( CBasePlayer *pPlayer, CBaseEntity *pObject ) { // Holster player's weapon if ( pPlayer->GetActiveWeapon() ) { if ( !pPlayer->GetActiveWeapon()->CanHolster() || !pPlayer->GetActiveWeapon()->Holster() ) { Shutdown(); return; } } // If the target is debris, convert it to non-debris if ( pObject->GetCollisionGroup() == COLLISION_GROUP_DEBRIS ) { // Interactive debris converts back to debris when it comes to rest pObject->SetCollisionGroup( COLLISION_GROUP_INTERACTIVE_DEBRIS ); } // done so I'll go across level transitions with the player SetParent( pPlayer ); m_grabController.SetIgnorePitch( true ); m_grabController.SetAngleAlignment( DOT_30DEGREE ); m_pPlayer = pPlayer; IPhysicsObject *pPhysics = pObject->VPhysicsGetObject(); Pickup_OnPhysGunPickup( pObject, m_pPlayer, PICKED_UP_BY_PLAYER ); m_grabController.AttachEntity( pPlayer, pObject, pPhysics, false, vec3_origin, false ); m_pPlayer->m_Local.m_iHideHUD |= HIDEHUD_WEAPONSELECTION; m_pPlayer->SetUseEntity( this ); }
void CPlayerPickupController::Init( CBasePlayer *pPlayer, CBaseEntity *pObject ) { m_pPlayer = pPlayer; IPhysicsObject *pPhysics = pObject->VPhysicsGetObject(); Vector position; QAngle angles; pPhysics->GetPosition( &position, &angles ); m_grabController.SetMaxImpulse( Vector(20*100,20*100,20*100), AngularImpulse(20*180,20*180,20*180) ); m_grabController.AttachEntity( pObject, pPhysics, position, angles ); // Holster player's weapon if ( m_pPlayer->GetActiveWeapon() ) { if ( !m_pPlayer->GetActiveWeapon()->Holster() ) { Shutdown(); return; } } m_pPlayer->m_Local.m_iHideHUD |= HIDEHUD_WEAPONS; m_pPlayer->SetUseEntity( this ); matrix3x4_t tmp; ComputePlayerMatrix( tmp ); VectorITransform( position, tmp, m_positionPlayerSpace ); // UNDONE: This algorithm needs a bit more thought. REVISIT. // put the bottom of the object arms' length below eye level // get bottommost point of object Vector bottom = physcollision->CollideGetExtent( pPhysics->GetCollide(), vec3_origin, angles, Vector(0,0,-1) ); // get the real eye origin Vector playerEye = pPlayer->EyePosition(); // move target up so that bottom of object is at PLAYER_HOLD_LEVEL z in local space // float delta = PLAYER_HOLD_LEVEL_EYES - bottom.z - m_positionPlayerSpace.z; float delta = 0; // player can reach down 2ft below his feet float maxPickup = (playerEye.z + PLAYER_HOLD_LEVEL_EYES) - (pPlayer->GetAbsMins().z - PLAYER_REACH_DOWN_DISTANCE); delta = clamp( delta, pPlayer->WorldAlignMins().z, maxPickup ); m_positionPlayerSpace.z += delta; m_anglesPlayerSpace = TransformAnglesToLocalSpace( angles, tmp ); m_anglesPlayerSpace = AlignAngles( m_anglesPlayerSpace, DOT_30DEGREE ); // re-transform and check angles = TransformAnglesToWorldSpace( m_anglesPlayerSpace, tmp ); VectorTransform( m_positionPlayerSpace, tmp, position ); // hackhack: Move up to eye position for the check float saveZ = position.z; position.z = playerEye.z; CheckObjectPosition( position, angles, position ); // move back to original position position.z = saveZ; VectorITransform( position, tmp, m_positionPlayerSpace ); }
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 CPlayerPickupController::CheckObjectPosition( Vector &position, const QAngle &angles, const Vector &oldPosition ) { CBaseEntity *pAttached = m_grabController.GetAttached(); trace_t tr; // move radially away from the player and check for space Vector offsetDir = position - m_pPlayer->GetAbsOrigin(); offsetDir.z = 0; VectorNormalize(offsetDir); Vector startSweep = position + offsetDir * pAttached->EntitySpaceSize().Length(); TraceCollideAgainstBBox( pAttached->VPhysicsGetObject()->GetCollide(), startSweep, position, angles, m_pPlayer->GetAbsOrigin(), m_pPlayer->WorldAlignMins(), m_pPlayer->WorldAlignMaxs(), &tr ); if ( tr.fraction != 1.0 ) { // if you hit, back off 4 inches and set that as the target // otherwise, you made it all the way and the position is fine if ( tr.startsolid ) { position = oldPosition; } else { position = tr.endpos + offsetDir * 2; } } }
void CPlayerPickupController::Shutdown() { m_pPlayer->SetUseEntity( NULL ); m_grabController.DetachEntity(); if ( m_pPlayer->GetActiveWeapon() ) { m_pPlayer->GetActiveWeapon()->Deploy(); } m_pPlayer->m_Local.m_iHideHUD &= ~HIDEHUD_WEAPONS; Remove(); }
void CPlayerPickupController::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) { if ( ToBasePlayer(pActivator) == m_pPlayer ) { CBaseEntity *pAttached = m_grabController.GetAttached(); if ( !pAttached || useType == USE_OFF || m_grabController.ComputeError() > 12 || (m_pPlayer->m_nButtons & (IN_ATTACK|IN_ATTACK2)) ) { Shutdown(); return; } else if ( useType == USE_SET ) { // update position matrix3x4_t tmp; ComputePlayerMatrix( tmp ); Vector position; QAngle angles; VectorTransform( m_positionPlayerSpace, tmp, position ); angles = TransformAnglesToWorldSpace( m_anglesPlayerSpace, tmp ); CheckObjectPosition( position, angles, pAttached->GetAbsOrigin() ); // check to see if object is still sitting on something trace_t tr; Vector down = Vector( 0, 0, -6 ); UTIL_TraceEntity( pAttached, position, position + down, MASK_SOLID, &tr ); // if trace made it then there's nothing left to sit on, break the tie if ( tr.fraction == 1 ) { Shutdown(); return; } else { m_grabController.SetTargetPosition( position, angles ); } } } }
//----------------------------------------------------------------------------- // Purpose: // Input : bool - //----------------------------------------------------------------------------- void CPlayerPickupController::Shutdown( bool bThrown ) { CBaseEntity *pObject = m_grabController.GetAttached(); bool bClearVelocity = false; if ( !bThrown && pObject && pObject->VPhysicsGetObject() && pObject->VPhysicsGetObject()->GetContactPoint(NULL,NULL) ) { bClearVelocity = true; } CSDKPlayer *pOwner = (CSDKPlayer *)To_SDKPlayer( m_pPlayer ); pOwner->ClearUsePickup(); m_grabController.DetachEntity( bClearVelocity ); if ( pObject != NULL ) { Pickup_OnPhysGunDrop( pObject, m_pPlayer, bThrown ? THROWN_BY_PLAYER : DROPPED_BY_PLAYER ); } if ( m_pPlayer ) { m_pPlayer->SetUseEntity( NULL ); if ( m_pPlayer->GetActiveWeapon() ) { if ( !m_pPlayer->GetActiveWeapon()->Deploy() ) { // We tried to restore the player's weapon, but we couldn't. // This usually happens when they're holding an empty weapon that doesn't // autoswitch away when out of ammo. Switch to next best weapon. m_pPlayer->SwitchToNextBestWeapon( NULL ); } } m_pPlayer->m_Local.m_iHideHUD &= ~HIDEHUD_WEAPONSELECTION; } Remove(); }
//----------------------------------------------------------------------------- // Purpose: // Input : *pEnt - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool CPlayerPickupController::IsHoldingEntity( CBaseEntity *pEnt ) { return ( m_grabController.GetAttached() == pEnt ); }