//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// // // Purpose: // // $NoKeywords: $ //===========================================================================// #include "cbase.h" #include "c_prop_weightedcube.h" #include "portal_grabcontroller_shared.h" #include "c_portal_player.h" IMPLEMENT_CLIENTCLASS_DT( C_PropWeightedCube, DT_PropWeightedCube, CPropWeightedCube ) END_RECV_TABLE() LINK_ENTITY_TO_CLASS( prop_weighted_cube, C_PropWeightedCube ); CUtlVector C_PropWeightedCube::s_AllWeightedCubes; extern void ComputePlayerMatrix( CBasePlayer *pPlayer, matrix3x4_t &out ); QAngle C_PropWeightedCube::PreferredCarryAngles( void ) { static QAngle s_prefAngles; s_prefAngles = (m_qPreferredPlayerCarryAngles.x < FLT_MAX) ? m_qPreferredPlayerCarryAngles : vec3_angle; CBasePlayer *pPlayer = GetPlayerHoldingEntity( this ); if ( pPlayer ) { Vector vecRight; AngleVectors( pPlayer->EyeAngles(), NULL, &vecRight, NULL ); Quaternion qRotation; AxisAngleQuaternion( vecRight, pPlayer->EyeAngles().x, qRotation ); matrix3x4_t tmp; ComputePlayerMatrix( pPlayer, tmp ); QAngle qTemp = TransformAnglesToWorldSpace( s_prefAngles, tmp ); Quaternion qExisting; AngleQuaternion( qTemp, qExisting ); Quaternion qFinal; QuaternionMult( qRotation, qExisting, qFinal ); QuaternionAngles( qFinal, qTemp ); s_prefAngles = TransformAnglesToLocalSpace( qTemp, tmp ); } return s_prefAngles; } const Vector& C_PropWeightedCube::GetRenderOrigin( void ) { if( GetPredictable() ) { C_Portal_Player *pPlayer = (C_Portal_Player *)GetPlayerHoldingEntity( this ); if( pPlayer && pPlayer->GetGrabController().GetAttached() == this ) { //predicted grab controllers will almost never get the prediction correct. Which nukes our interpolation histories, resulting in jittery movement //workaround this by using the nuke-safe interpolation history directly in the grab controller return pPlayer->GetGrabController().GetHeldObjectRenderOrigin(); } } return BaseClass::GetRenderOrigin(); } void C_PropWeightedCube::UpdateOnRemove( void ) { s_AllWeightedCubes.FindAndFastRemove( this ); BaseClass::UpdateOnRemove(); } void C_PropWeightedCube::Spawn( void ) { BaseClass::Spawn(); s_AllWeightedCubes.AddToTail( this ); } //At some point it would be good to generalize this function to handle all MOVETYPE_VPHYSICS entities //But we're close to cert for Portal 2. So the scope at the moment is kept small. void MoveUnpredictedPhysicsNearPlayerToNetworkedPosition( CBasePlayer *pPlayer ) { Vector vPlayerCenter = pPlayer->WorldSpaceCenter(); for( int i = 0; i != C_PropWeightedCube::s_AllWeightedCubes.Count(); ++i ) { C_PropWeightedCube *pCube = C_PropWeightedCube::s_AllWeightedCubes[i]; if( !pCube->GetPredictable() && ((vPlayerCenter - pCube->WorldSpaceCenter()).LengthSqr() < (512.0f * 512.0f)) ) { pCube->MoveToLastReceivedPosition(); } } }