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(); 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 ); } } } }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- bool CGrabController::UpdateObject( CBasePlayer *pPlayer, float flError ) { CBaseEntity *pEntity = GetAttached(); if ( !pEntity || ComputeError() > flError || pPlayer->GetGroundEntity() == pEntity || !pEntity->VPhysicsGetObject() ) { return false; } //Adrian: Oops, our object became motion disabled, let go! IPhysicsObject *pPhys = pEntity->VPhysicsGetObject(); if ( pPhys && pPhys->IsMoveable() == false ) { return false; } Vector forward, right, up; QAngle playerAngles = pPlayer->EyeAngles(); AngleVectors( playerAngles, &forward, &right, &up ); float pitch = AngleDistance(playerAngles.x,0); if( !m_bAllowObjectOverhead ) { playerAngles.x = clamp( pitch, -75, 75 ); } else { playerAngles.x = clamp( pitch, -90, 75 ); } // Now clamp a sphere of object radius at end to the player's bbox Vector radial = physcollision->CollideGetExtent( pPhys->GetCollide(), vec3_origin, pEntity->GetAbsAngles(), -forward ); Vector player2d = pPlayer->CollisionProp()->OBBMaxs(); float playerRadius = player2d.Length2D(); float radius = playerRadius + fabs(DotProduct( forward, radial )); float distance = 24 + ( radius * 2.0f ); // Add the prop's distance offset distance += m_flDistanceOffset; Vector start = pPlayer->Weapon_ShootPosition(); Vector end = start + ( forward * distance ); trace_t tr; CTraceFilterSkipTwoEntities traceFilter( pPlayer, pEntity, COLLISION_GROUP_NONE ); Ray_t ray; ray.Init( start, end ); enginetrace->TraceRay( ray, MASK_SOLID_BRUSHONLY, &traceFilter, &tr ); if ( tr.fraction < 0.5 ) { end = start + forward * (radius*0.5f); } else if ( tr.fraction <= 1.0f ) { end = start + forward * ( distance - radius ); } Vector playerMins, playerMaxs, nearest; pPlayer->CollisionProp()->WorldSpaceAABB( &playerMins, &playerMaxs ); Vector playerLine = pPlayer->CollisionProp()->WorldSpaceCenter(); CalcClosestPointOnLine( end, playerLine+Vector(0,0,playerMins.z), playerLine+Vector(0,0,playerMaxs.z), nearest, NULL ); if( !m_bAllowObjectOverhead ) { Vector delta = end - nearest; float len = VectorNormalize(delta); if ( len < radius ) { end = nearest + radius * delta; } } //Show overlays of radius if ( g_debug_physcannon.GetBool() ) { NDebugOverlay::Box( end, -Vector( 2,2,2 ), Vector(2,2,2), 0, 255, 0, true, 0 ); NDebugOverlay::Box( GetAttached()->WorldSpaceCenter(), -Vector( radius, radius, radius), Vector( radius, radius, radius ), 255, 0, 0, true, 0.0f ); } QAngle angles = TransformAnglesFromPlayerSpace( m_attachedAnglesPlayerSpace, pPlayer ); // If it has a preferred orientation, update to ensure we're still oriented correctly. Pickup_GetPreferredCarryAngles( pEntity, pPlayer, pPlayer->EntityToWorldTransform(), angles ); // We may be holding a prop that has preferred carry angles if ( m_bHasPreferredCarryAngles ) { matrix3x4_t tmp; ComputePlayerMatrix( pPlayer, tmp ); angles = TransformAnglesToWorldSpace( m_vecPreferredCarryAngles, tmp ); } matrix3x4_t attachedToWorld; Vector offset; AngleMatrix( angles, attachedToWorld ); VectorRotate( m_attachedPositionObjectSpace, attachedToWorld, offset ); SetTargetPosition( end - offset, angles ); return true; }