Exemplo n.º 1
0
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);
	}
}
Exemplo n.º 2
0
void CNodeController::UpdateHeadFollowObjControl(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 object position...
    LTVector vObjPos;

	if(pNodeControl->hFollowObjNode == INVALID_MODEL_NODE)
	{
		// Just get the position of the follow object if the follow node is invalid
        g_pLTClient->GetObjectPos(pNodeControl->hFollowObj, &vObjPos);
	}
	else
	{
		// Get the transform of the node we're following
        pModelLT->GetNodeTransform(pNodeControl->hFollowObj, pNodeControl->hFollowObjNode, transform, LTTRUE);

		// Decompose the transform into the position and rotation
		pTransformLT->GetPos(transform, vObjPos);
	}

	// 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;
}