bool PlayerLureFX::Reset( ) { // Get the client player object. HOBJECT hObj = g_pMoveMgr->GetObject( ); if( !hObj ) { ASSERT( !"PlayerLureFX::GetOffsetTransform: Missing client-side player object." ); return false; } // Get the client player's position. LTransform playerTransform; g_pLTClient->GetObjectPos( hObj, &playerTransform.m_Pos ); g_pLTClient->GetObjectRotation( hObj, &playerTransform.m_Rot ); playerTransform.m_Scale.Init( 1.0f, 1.0f, 1.0f ); // Get the playerlure's transform. LTransform playerLureTransform; g_pLTClient->GetObjectPos( GetServerObj( ), &playerLureTransform.m_Pos ); g_pLTClient->GetObjectRotation( GetServerObj( ), &playerLureTransform.m_Rot ); playerLureTransform.m_Scale.Init( 1.0f, 1.0f, 1.0f ); // Find the offset transform. ILTTransform *pTransformLT = g_pLTClient->GetTransformLT(); pTransformLT->Difference( m_offsetTransform, playerTransform, playerLureTransform ); m_offsetTransform.m_Scale.Init( 1.0f, 1.0f, 1.0f ); return true; }
bool WorldModel::AttachServerMark( CServerMark& mark, CLIENTWEAPONFX & theStruct) { LTransform globalTransform, parentTransform, localTransform; ILTTransform *pTransformLT; LTVector vParentPos, vOffset; LTRotation rParentRot, rRot; LTRotation rOffset; pTransformLT = g_pLTServer->GetTransformLT(); // Attach the mark to the parent object... // Figure out what the rotation we want is. rOffset.Init(); rRot = LTRotation(theStruct.vSurfaceNormal, LTVector(0.0f, 1.0f, 0.0f)); // MD // Ok, now we have the transform in global space but attachments are specified in // local space (so they can move as the object moves and rotates). // Set the global LTransform. pTransformLT->Set(globalTransform, theStruct.vPos, rRot); // Get the object's transform. g_pLTServer->GetObjectPos( m_hObject, &vParentPos); g_pLTServer->GetObjectRotation( m_hObject, &rParentRot); parentTransform.m_Pos = vParentPos; parentTransform.m_Rot = rParentRot; parentTransform.m_Scale.Init(1,1,1); globalTransform.m_Scale.Init(1,1,1); // Get the offset. pTransformLT->Difference(localTransform, globalTransform, parentTransform); vOffset = localTransform.m_Pos; rOffset = localTransform.m_Rot; HATTACHMENT hAttachment = NULL; LTRESULT dRes = g_pLTServer->CreateAttachment( m_hObject, mark.m_hObject, LTNULL, &vOffset, &rOffset, &hAttachment); if (dRes != LT_OK) { return false; } // Add to the attachment list. LTObjRefNotifier ref( *this ); ref = mark.m_hObject; m_AttachmentList.push_back( ref ); return true; }
void CNodeController::HandleNodeControlRecoilMessage(HMESSAGEREAD hMessage) { if ( m_cRecoils >= MAX_RECOILS ) return; m_fRecoilTimers[m_cRecoils++] = 0.50f; ModelNode eModelNode; eModelNode = (ModelNode)g_pLTClient->ReadFromMessageByte(hMessage); LTVector vRecoilDir; g_pLTClient->ReadFromMessageCompVector(hMessage, &vRecoilDir); // Get the magnitude of the recoil vector LTFLOAT fRecoilMag = VEC_MAGSQR(vRecoilDir); // Get the unit impact/recoil vector vRecoilDir /= (float)sqrt(fRecoilMag); // Cap it if necessary if ( fRecoilMag > 100.0f ) { fRecoilMag = 100.0f; } // Get the position of the impact NSTRUCT* pNode = &m_aNodes[eModelNode]; ILTModel* pModelLT = g_pLTClient->GetModelLT(); LTransform transform; pModelLT->GetNodeTransform(GetCFX()->GetServerObj(), pNode->hModelNode, transform, LTTRUE); // Decompose the transform into the position and rotation LTVector vPos; ILTTransform* pTransformLT = g_pLTClient->GetTransformLT(); pTransformLT->GetPos(transform, vPos); LTVector vRecoilPos = vPos; // Add angular rotations up the recoil parent chain ModelNode eModelNodeCurrent = g_pModelButeMgr->GetSkeletonNodeRecoilParent(GetCFX()->GetModelSkeleton(), eModelNode); while ( eModelNodeCurrent != eModelNodeInvalid ) { // Get the rotation of the node NSTRUCT* pNode = &m_aNodes[eModelNodeCurrent]; LTransform transform; ILTModel* pModelLT = g_pLTClient->GetModelLT(); // Get the transform of the node we're controlling pModelLT->GetNodeTransform(GetCFX()->GetServerObj(), pNode->hModelNode, transform, LTTRUE); ILTTransform* pTransformLT = g_pLTClient->GetTransformLT(); // Decompose the transform into the position and rotation LTVector vPos; LTRotation rRot; pTransformLT->Get(transform, vPos, rRot); // Get the rotation vectors of the transform LTVector vRight, vUp, vForward; g_pLTClient->GetRotationVectors(&rRot, &vUp, &vRight, &vForward); // Cross the right vector with the impact vector to get swing LTVector vRotationAxis = vRight.Cross(vRecoilDir); vRotationAxis.Norm(); // Add the timed rotation control for the swing // !!! HACK // !!! Do not add swing if this is a leg node if ( !strstr(g_pModelButeMgr->GetSkeletonNodeName(GetCFX()->GetModelSkeleton(), eModelNodeCurrent), "leg") ) AddNodeControlRotationTimed(eModelNodeCurrent, vRotationAxis, MATH_PI/1000.0f*fRecoilMag, 0.50f); // Use the right vector to get twist, but make sure the sign is correct based on location // of impact and whether we're getting shot at from behind/front etc vRotationAxis = vRight; vRotationAxis.Norm(); // Get the twist LTVector vSideDir = vRecoilPos-vPos; vSideDir.Norm(); LTFLOAT fSign = vUp.Dot(vRecoilDir); fSign *= vForward.Dot(vSideDir); if ( fSign > 0.0f ) { vRotationAxis = -vRotationAxis; } // Add the timed rotation control for the twist // AddNodeControlRotationTimed(eModelNodeCurrent, vRotationAxis, MATH_PI/1000.0f*fRecoilMag, 0.50f); // Decrease the magnitude fRecoilMag /= 2.0f; eModelNodeCurrent = g_pModelButeMgr->GetSkeletonNodeRecoilParent(GetCFX()->GetModelSkeleton(), eModelNodeCurrent); } }
void CNodeController::UpdateHeadFollowPosControl(NCSTRUCT *pNodeControl) { LTVector vPos; LTRotation rRot; LTransform transform; LTVector vU, vR, vF; //---------------------------------------------------------------------- // Get information about the control node... // *** NOTE: On the head node... vU faces forward, vR faces down, vF faces right *** // Get access to the controls... ILTMath *pMathLT = g_pLTClient->GetMathLT(); ILTModel *pModelLT = g_pLTClient->GetModelLT(); ILTTransform *pTransformLT = g_pLTClient->GetTransformLT(); // Get the transform of the node we're controlling pModelLT->GetNodeTransform(GetCFX()->GetServerObj(), m_aNodes[pNodeControl->eModelNode].hModelNode, transform, LTTRUE); // Decompose the transform into the position and rotation pTransformLT->Get(transform, vPos, rRot); pMathLT->GetRotationVectors(rRot, vR, vU, vF); // Get information about the follow position... LTVector vObjPos = pNodeControl->vFollowPos; // Turn the follow control off if the expire time has past if(pNodeControl->fFollowExpireTime <= 0.0f) { pNodeControl->fFollowExpireTime = 0.0f; pNodeControl->bFollowOn = LTFALSE; } else pNodeControl->fFollowExpireTime -= g_pGameClientShell->GetFrameTime(); //---------------------------------------------------------------------- // Setup the rotation matrix to directly follow the destination position // Get the direction that we're going to face... LTVector vDir = vObjPos - vPos; // Setup some temp vectors that are on the x/z plane... LTVector vTempU, vTempF, vTempDir; vTempU = vU; vTempU.y = 0.0f; vTempF = vF; vTempF.y = 0.0f; vTempDir = vDir; vTempDir.y = 0.0f; VEC_NORM(vTempU); VEC_NORM(vTempF); VEC_NORM(vTempDir); // Get the dot products between the dir vector and the up and forward to determine the rotation angles LTFLOAT fDotUDir = VEC_DOT(vTempU, vTempDir); LTFLOAT fDotFDir = VEC_DOT(vTempF, vTempDir); LTFLOAT fDotRDir = 0.0f; // Init the vectors to get a rotation matrix from... LTVector vRotAxisR(1.0f, 0.0f, 0.0f); // Get the first rotation angle LTFLOAT fAngle1 = pNodeControl->bFollowOn ? fDotUDir : 1.0f; if(fAngle1 < -0.1f) fAngle1 = -0.1f; // HACK! Limit the head rotation fAngle1 = (1.0f - fAngle1) * MATH_HALFPI; if(fDotFDir < 0.0f) fAngle1 *= -1.0f; // Do a full rotation around the first axis so we can get an angle for the second axis LTFLOAT fTempAngle = pNodeControl->bFollowOn ? ((1.0f - fDotUDir) * MATH_HALFPI) : 0.0f; pMathLT->RotateAroundAxis(rRot, vR, (fDotFDir < 0.0f) ? -fTempAngle : fTempAngle); pMathLT->GetRotationVectors(rRot, vR, vU, vF); VEC_NORM(vDir); fDotUDir = VEC_DOT(vU, vDir); fDotRDir = VEC_DOT(vR, vDir); // Get the second rotation angle LTFLOAT fAngle2 = pNodeControl->bFollowOn ? fDotUDir : 1.0f; if(fAngle2 < 0.25f) fAngle2 = 0.25f; // HACK! Limit the head rotation fAngle2 = (1.0f - fAngle2) * MATH_HALFPI; if(fDotRDir > 0.0f) fAngle2 *= -1.0f; // Calculate a max rotation value LTFLOAT fRotMax = (pNodeControl->fFollowRate * g_pGameClientShell->GetFrameTime() / 180.0f) * MATH_PI; // Interpolate the angles based off the previous angle if(fAngle1 > pNodeControl->vFollowAngles.y + fRotMax) fAngle1 = pNodeControl->vFollowAngles.y + fRotMax; else if(fAngle1 < pNodeControl->vFollowAngles.y - fRotMax) fAngle1 = pNodeControl->vFollowAngles.y - fRotMax; if(fAngle2 > pNodeControl->vFollowAngles.x + fRotMax) fAngle2 = pNodeControl->vFollowAngles.x + fRotMax; else if(fAngle2 < pNodeControl->vFollowAngles.x - fRotMax) fAngle2 = pNodeControl->vFollowAngles.x - fRotMax; // Create a new rotation and rotate around each controlled axis LTRotation rNewRot; rNewRot.Init(); pMathLT->RotateAroundAxis(rNewRot, vRotAxisR, fAngle1); pNodeControl->vFollowAngles.y = fAngle1; pMathLT->GetRotationVectors(rNewRot, vR, vU, vF); pMathLT->RotateAroundAxis(rNewRot, vF, fAngle2); pNodeControl->vFollowAngles.x = fAngle2; // If we're turned off and back at the start rotation... make the control invalid if(!pNodeControl->bFollowOn && pNodeControl->vFollowAngles.x == 0.0f && pNodeControl->vFollowAngles.y == 0.0f) { pNodeControl->bValid = LTFALSE; return; } // Create a rotation matrix and apply it to the current offset matrix LTMatrix m1; pMathLT->SetupRotationMatrix(m1, rNewRot); m_aNodes[pNodeControl->eModelNode].matTransform = m_aNodes[pNodeControl->eModelNode].matTransform * m1; }