BVB Source Codes

CRYENGINE Show VehicleSeatActionRotateTurret.cpp Source code

Return Download CRYENGINE: download VehicleSeatActionRotateTurret.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. /*************************************************************************
  4.    -------------------------------------------------------------------------
  5.    $Id$
  6.    $DateTime$
  7.    Description: Implements a seat action to rotate a turret
  8.  
  9.    -------------------------------------------------------------------------
  10.    History:
  11.    - 14:12:2005: Created by Mathieu Pinard
  12.  
  13. *************************************************************************/
  14. #include "StdAfx.h"
  15.  
  16. #include "VehicleSeatActionRotateTurret.h"
  17.  
  18. #include "GameObjects/GameObject.h"
  19. #include "IGameObject.h"
  20. #include "IVehicleSystem.h"
  21. #include "Vehicle.h"
  22. #include "VehicleSeat.h"
  23. #include "VehiclePartBase.h"
  24. #include "VehiclePartAnimated.h"
  25.  
  26. #include "VehicleSeatActionWeapons.h"
  27.  
  28. #include "PersistantDebug.h"
  29. #include <CryRenderer/IRenderAuxGeom.h>
  30.  
  31. //------------------------------------------------------------------------
  32. bool CVehicleSeatActionRotateTurret::Init(IVehicle* pVehicle, IVehicleSeat* pSeat, const CVehicleParams& table)
  33. {
  34.         m_pUserEntity = NULL;
  35.         m_aimGoal.zero();
  36.         m_aimGoalPriority = 0;
  37.  
  38.         m_rotTestHelpers[0] = NULL;
  39.         m_rotTestHelpers[1] = NULL;
  40.         m_rotTestRadius = 0.f;
  41.  
  42.         m_pVehicle = static_cast<CVehicle*>(pVehicle);
  43.         m_pSeat = static_cast<CVehicleSeat*>(pSeat);
  44.         assert(m_pSeat);
  45.  
  46.         CVehicleParams rotationTable = table.findChild("RotateTurret");
  47.         if (!rotationTable)
  48.                 return false;
  49.  
  50.         // first the actual rotation setups
  51.         if (CVehicleParams pitchTable = rotationTable.findChild("Pitch"))
  52.         {
  53.                 InitRotation(pVehicle, pitchTable, eVTRT_Pitch);
  54.                 InitRotationSounds(pitchTable, eVTRT_Pitch);
  55.         }
  56.         if (CVehicleParams yawTable = rotationTable.findChild("Yaw"))
  57.         {
  58.                 InitRotation(pVehicle, yawTable, eVTRT_Yaw);
  59.                 InitRotationSounds(yawTable, eVTRT_Yaw);
  60.         }
  61.  
  62.         // then the (optional) rotation testing
  63.         if (CVehicleParams rotationTestTable = rotationTable.findChild("RotationTest"))
  64.         {
  65.                 if (rotationTestTable.haveAttr("helper1"))
  66.                 {
  67.                         const char* helpName = rotationTestTable.getAttr("helper1");
  68.                         if (IVehicleHelper* pHelper = m_pVehicle->GetHelper(helpName))
  69.                                 m_rotTestHelpers[0] = pHelper;
  70.                 }
  71.                 if (rotationTestTable.haveAttr("helper2"))
  72.                 {
  73.                         const char* helpName = rotationTestTable.getAttr("helper2");
  74.                         if (IVehicleHelper* pHelper = m_pVehicle->GetHelper(helpName))
  75.                                 m_rotTestHelpers[1] = pHelper;
  76.                 }
  77.  
  78.                 rotationTestTable.getAttr("radius", m_rotTestRadius);
  79.         }
  80.  
  81.         return true;
  82. }
  83.  
  84. //------------------------------------------------------------------------
  85. void CVehicleSeatActionRotateTurret::Reset()
  86. {
  87.         m_aimGoal.zero();
  88. }
  89.  
  90. //------------------------------------------------------------------------
  91. void CVehicleSeatActionRotateTurret::StartUsing(EntityId passengerId)
  92. {
  93.         m_pUserEntity = gEnv->pEntitySystem->GetEntity(passengerId);
  94.         m_aimGoal.zero();
  95.  
  96.         IVehiclePart::SVehiclePartEvent partEvent;
  97.         partEvent.type = IVehiclePart::eVPE_StartUsing;
  98.  
  99.         m_pVehicle->SetObjectUpdate(this, IVehicle::eVOU_AlwaysUpdate);
  100.  
  101.         for (int i = 0; i < eVTRT_NumRotationTypes; ++i)
  102.         {
  103.                 if (m_rotations[i].m_pPart)
  104.                 {
  105.                         m_rotations[i].m_relSpeed = 0.0f;
  106.                         m_rotations[i].m_prevWorldQuat = Quat(m_rotations[i].m_pPart->GetWorldTM());
  107.                         m_rotations[i].m_pPart->OnEvent(partEvent);
  108.                 }
  109.         }
  110. }
  111.  
  112. //------------------------------------------------------------------------
  113. void CVehicleSeatActionRotateTurret::StopUsing()
  114. {
  115.         m_pUserEntity = NULL;
  116.         m_aimGoal.zero();
  117.  
  118.         IVehiclePart::SVehiclePartEvent partEvent;
  119.         partEvent.type = IVehiclePart::eVPE_StopUsing;
  120.  
  121.         for (int i = 0; i < eVTRT_NumRotationTypes; ++i)
  122.         {
  123.                 if (m_rotations[i].m_pPart)
  124.                 {
  125.                         m_rotations[i].m_pPart->OnEvent(partEvent);
  126.                         m_rotations[i].m_relSpeed = 0.f;
  127.                         m_pVehicle->StopSound(m_rotations[i].m_turnSoundId);
  128.                         m_pVehicle->StopSound(m_rotations[i].m_damageSoundId);
  129.                 }
  130.         }
  131.  
  132.         m_pVehicle->SetObjectUpdate(this, IVehicle::eVOU_NoUpdate);
  133. }
  134.  
  135. //------------------------------------------------------------------------
  136. void CVehicleSeatActionRotateTurret::OnAction(const TVehicleActionId actionId, int activationMode, float value)
  137. {
  138.         if (!m_aimGoal.IsZero())
  139.         {
  140.                 // if seat action is used remotely, rotation is set through aim goal, thus return here
  141.                 if (m_pSeat && m_pSeat->GetCurrentTransition() == CVehicleSeat::eVT_RemoteUsage)
  142.                         return;
  143.         }
  144.  
  145.         if (actionId == eVAI_RotatePitch && m_rotations[eVTRT_Pitch].m_pPart)
  146.         {
  147.                 m_rotations[eVTRT_Pitch].m_action = -value;
  148.         }
  149.         else if (actionId == eVAI_RotateYaw && m_rotations[eVTRT_Yaw].m_pPart)
  150.         {
  151.                 m_rotations[eVTRT_Yaw].m_action = -value;
  152.         }
  153.  
  154.         if (actionId == eVAI_RotatePitchAimAssist && m_rotations[eVTRT_Pitch].m_pPart)
  155.         {
  156.                 m_rotations[eVTRT_Pitch].m_aimAssist = value;
  157.         }
  158.         else if (actionId == eVAI_RotateYawAimAssist && m_rotations[eVTRT_Yaw].m_pPart)
  159.         {
  160.                 m_rotations[eVTRT_Yaw].m_aimAssist = value;
  161.         }
  162.  
  163.         if (m_pSeat)
  164.                 m_pSeat->ChangedNetworkState(CVehicle::ASPECT_PART_MATRIX);
  165. }
  166.  
  167. //------------------------------------------------------------------------
  168. void CVehicleSeatActionRotateTurret::Serialize(TSerialize ser, EEntityAspects aspects)
  169. {
  170.         // MR: for network, only turret parts are serialized
  171.         // for savegame, all parts are serialized (by CVehicle)
  172.         if (ser.GetSerializationTarget() == eST_Network)
  173.         {
  174.                 for (int i = 0; i < eVTRT_NumRotationTypes; ++i)
  175.                 {
  176.                         if (m_rotations[i].m_pPart)
  177.                         {
  178.                                 m_rotations[i].m_pPart->Serialize(ser, aspects);
  179.                         }
  180.                 }
  181.         }
  182.         else
  183.         {
  184.                 // save rotation details
  185.                 CryFixedStringT<16> tag;
  186.                 for (int i = 0; i < eVTRT_NumRotationTypes; ++i)
  187.                 {
  188.                         if (m_rotations[i].m_pPart)
  189.                         {
  190.                                 Quat q;
  191.                                 Matrix34 currentTM = m_rotations[i].m_pPart->GetLocalBaseTM();
  192.                                 if (ser.IsWriting())
  193.                                         q = Quat(currentTM);
  194.  
  195.                                 tag = (i == eVTRT_Pitch) ? "rotation_pitch" : "rotation_yaw";
  196.                                 ser.Value(tag.c_str(), q, 'ori1');
  197.  
  198.                                 if (ser.IsReading())
  199.                                 {
  200.                                         Matrix34 newTM(q);
  201.                                         newTM.SetTranslation(currentTM.GetTranslation());
  202.                                         m_rotations[i].m_pPart->SetLocalBaseTM(newTM);
  203.                                         m_rotations[i].m_orientation.Set(q);
  204.                                 }
  205.                         }
  206.                 }
  207.         }
  208. }
  209.  
  210. //------------------------------------------------------------------------
  211. void CVehicleSeatActionRotateTurret::Update(float frameTime)
  212. {
  213.         if (!m_pUserEntity)
  214.         {
  215.                 DoUpdate(frameTime);
  216.         }
  217. }
  218.  
  219. void CVehicleSeatActionRotateTurret::UpdateFromPassenger(const float frameTime, EntityId playerId)
  220. {
  221.         if (m_pUserEntity && (m_pUserEntity->GetId() == playerId))
  222.         {
  223.                 DoUpdate(frameTime);
  224.         }
  225. }
  226.  
  227. void CVehicleSeatActionRotateTurret::DoUpdate(const float frameTime)
  228. {
  229.         FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION);
  230.  
  231.         if (gEnv->IsClient() && m_pVehicle->IsProbablyDistant() && !m_pVehicle->GetGameObject()->IsProbablyVisible())
  232.                 return;
  233.  
  234.         // AI use the aim goal to control their rotation (remote usage too)
  235.         if (!m_aimGoal.IsZero())
  236.         {
  237.                 UpdateAimGoal();
  238.         }
  239.  
  240.         // Cache the helper position before applying any rotation
  241.         IActor* pActor = m_pSeat->GetPassengerActor();
  242.         bool checkRotation = (m_rotTestHelpers[0] && m_rotTestHelpers[1] && pActor);
  243.         Vec3 oldHelperPos = checkRotation ? m_rotTestHelpers[1]->GetWorldSpaceTranslation() : Vec3(ZERO);
  244.  
  245.         Matrix34 oldMatrices[eVTRT_NumRotationTypes];
  246.  
  247.         for (int i = 0; i < eVTRT_NumRotationTypes; ++i)
  248.         {
  249.                 if (m_rotations[i].m_pPart)
  250.                 {
  251.                         oldMatrices[i] = m_rotations[i].m_pPart->GetLocalBaseTM();
  252.                         UpdatePartRotation((EVehicleTurretRotationType)i, frameTime);
  253.                 }
  254.         }
  255.  
  256.         // Check for turret collisions
  257.         if (checkRotation)
  258.         {
  259.                 // need to test the new rotations before applying them. Sweep a sphere between the two helpers and check for collisions...
  260.                 static IPhysicalEntity* pSkipEntities[10];
  261.                 int numSkip = m_pVehicle->GetSkipEntities(pSkipEntities, 10);
  262.                 primitives::sphere sphere;
  263.                 sphere.center = m_rotTestHelpers[0]->GetWorldSpaceTranslation();
  264.                 sphere.r = m_rotTestRadius;
  265.  
  266.                 geom_contact* pContact = NULL;
  267.                 Vec3 dir = m_rotTestHelpers[1]->GetWorldSpaceTranslation() - sphere.center;
  268.                 float hit = gEnv->pPhysicalWorld->PrimitiveWorldIntersection(sphere.type, &sphere, dir, ent_static | ent_terrain | ent_rigid | ent_sleeping_rigid, &pContact, 0, (geom_colltype_player << rwi_colltype_bit) | rwi_stop_at_pierceable, 0, 0, 0, pSkipEntities, numSkip);
  269.                 if (hit > 0.001f && pContact)
  270.                 {
  271.                         // there was a collision. check whether the barrel is moving towards the collision point or not... if not, ignore the collision.
  272. #if ENABLE_VEHICLE_DEBUG
  273.                         if (VehicleCVars().v_debugdraw > 0)
  274.                         {
  275.                                 CPersistantDebug* pPD = CCryAction::GetCryAction()->GetPersistantDebug();
  276.                                 pPD->Begin("VehicleCannon", false);
  277.  
  278.                                 ColorF col(1.0f, 0.0f, 0.0f, 1.0f);
  279.                                 if (pContact && hit > 0.0f)
  280.                                 {
  281.                                         pPD->AddSphere(pContact->pt, 0.1f, col, 30.0f);
  282.                                 }
  283.                         }
  284. #endif
  285.                         Vec3 endPos = m_rotTestHelpers[1]->GetWorldSpaceTranslation();
  286.                         Vec3 moveDir = endPos - oldHelperPos;
  287.                         Vec3 hitDir = pContact->pt - oldHelperPos;
  288.  
  289.                         if (moveDir.Dot(hitDir) > 0.0f)
  290.                         {
  291.                                 // reset as though the rotation never happened.
  292.                                 for (int i = 0; i < eVTRT_NumRotationTypes; ++i)
  293.                                 {
  294.                                         if (m_rotations[i].m_pPart)
  295.                                         {
  296.                                                 CVehiclePartBase* pPart = m_rotations[i].m_pPart;
  297.                                                 pPart->SetLocalBaseTM(oldMatrices[i]);
  298.                                                 const Matrix34& worldTM = pPart->GetWorldTM();
  299.                                                 m_rotations[i].m_prevWorldQuat = Quat(worldTM);
  300.                                                 m_rotations[i].m_orientation.Set(Quat(Matrix33(oldMatrices[i])));
  301.                                         }
  302.                                 }
  303.                         }
  304.                 }
  305.         }
  306.  
  307.         m_aimGoalPriority = 0;
  308. }
  309.  
  310. //------------------------------------------------------------------------
  311. void CVehicleSeatActionRotateTurret::UpdateAimGoal()
  312. {
  313.         Vec3 aimGoalLocal = m_pVehicle->GetEntity()->GetWorldTM().GetInverted() * m_aimGoal;
  314.  
  315.         IVehiclePart* pPitchPart = m_rotations[eVTRT_Pitch].m_pPart;
  316.         if (pPitchPart)
  317.         {
  318.                 Vec3 pitchPartToAimGoal = aimGoalLocal - pPitchPart->GetLocalTM(false).GetTranslation();
  319.  
  320.                 Quat pitchAimDir = Quat::CreateRotationVDir(pitchPartToAimGoal.GetNormalizedSafe());
  321.                 Ang3 desiredPitchAngles(pitchAimDir);
  322.  
  323.                 Ang3 currentPitchAngles(pPitchPart->GetLocalTM(false));
  324.                 m_rotations[eVTRT_Pitch].m_action = desiredPitchAngles.x - currentPitchAngles.x;
  325.         }
  326.  
  327.         IVehiclePart* pYawPart = m_rotations[eVTRT_Yaw].m_pPart;
  328.         if (pYawPart)
  329.         {
  330.                 Vec3 yawPartToAimGoal = aimGoalLocal - pYawPart->GetLocalTM(false).GetTranslation();
  331.  
  332.                 Quat yawAimDir = Quat::CreateRotationVDir(yawPartToAimGoal.GetNormalizedSafe());
  333.                 Ang3 desiredYawAngles(yawAimDir);
  334.  
  335.                 Ang3 currentYawAngles(pYawPart->GetLocalTM(false));
  336.                 m_rotations[eVTRT_Yaw].m_action = fmod(desiredYawAngles.z - currentYawAngles.z + 3.0f * gf_PI, gf_PI2) - gf_PI;
  337.         }
  338. }
  339.  
  340. void CVehicleSeatActionRotateTurret::MaintainPartRotationWorldSpace(EVehicleTurretRotationType eType)
  341. {
  342.         CVehiclePartBase* pPart = m_rotations[eType].m_pPart;
  343.         IVehiclePart* pParent = pPart->GetParent();
  344.         IActor* pActor = m_pSeat->GetPassengerActor();
  345.  
  346.         bool remote = m_pSeat->GetCurrentTransition() == IVehicleSeat::eVT_RemoteUsage;
  347.         bool worldSpace = m_rotations[eType].m_worldSpace && VehicleCVars().v_independentMountedGuns != 0;
  348.  
  349.         if (worldSpace && pParent && pActor && pActor->IsClient() && !remote)
  350.         {
  351.                 // we want to keep the old worldspace rotation
  352.                 // therefore we're updating the local transform from it
  353.                 // NB: there is no need to clamp here, its done later
  354.  
  355.                 Matrix34 localTM = pParent->GetWorldTM().GetInverted() * Matrix34(m_rotations[eType].m_prevWorldQuat);
  356.                 localTM.OrthonormalizeFast(); // precision issue
  357.  
  358.                 const Matrix34& baseTM = pPart->GetLocalBaseTM();
  359.  
  360.                 if (!Matrix34::IsEquivalent(baseTM, localTM))
  361.                 {
  362.                         Ang3 anglesCurr(baseTM);
  363.                         Ang3 angles(localTM);
  364.  
  365.                         if (eType == eVTRT_Pitch)
  366.                         {
  367.                                 angles.y = anglesCurr.y;
  368.                                 angles.z = anglesCurr.z;
  369.                         }
  370.                         else if (eType == eVTRT_Yaw)
  371.                         {
  372.                                 angles.x = anglesCurr.x;
  373.                                 angles.y = anglesCurr.y;
  374.                         }
  375.  
  376.                         localTM.SetRotationXYZ(angles);
  377.                         localTM.SetTranslation(baseTM.GetTranslation());
  378.                         pPart->SetLocalBaseTM(localTM);
  379.  
  380.                         m_pSeat->ChangedNetworkState(CVehicle::ASPECT_PART_MATRIX);
  381.                 }
  382.  
  383. #if ENABLE_VEHICLE_DEBUG
  384.                 if (VehicleCVars().v_debugdraw == eVDB_Parts)
  385.                 {
  386.                         float color[] = { 1, 1, 1, 1 };
  387.                         Ang3 a(localTM), aBase(baseTM);
  388.                         IRenderAuxText::Draw2dLabel(200, 200, 1.4f, color, false, "localAng: %.1f (real: %.1f)", RAD2DEG(a.z), RAD2DEG(aBase.z));
  389.                 }
  390. #endif
  391.         }
  392. }
  393.  
  394. //------------------------------------------------------------------------
  395. void CVehicleSeatActionRotateTurret::UpdatePartRotation(EVehicleTurretRotationType eType, float frameTime)
  396. {
  397.         CRY_ASSERT(eType < eVTRT_NumRotationTypes);
  398.  
  399.         const float threshold = 0.01f;
  400.         if (frameTime > 0.08f) frameTime = 0.08f;
  401.  
  402.         CVehiclePartBase* pPart = m_rotations[eType].m_pPart;
  403.         IVehiclePart* pParent = pPart->GetParent();
  404.         IActor* pActor = m_pSeat->GetPassengerActor();
  405.  
  406.         float rot_dir = fsgnf(m_rotations[eType].m_action);
  407.         float max_rotation = fabsf(m_rotations[eType].m_action);
  408.         float rot_speed = DEG2RAD(fabsf(m_rotations[eType].m_speed)) * GetDamageSpeedMul(pPart);
  409.  
  410.         float delta = rot_dir * rot_speed * frameTime;
  411.         delta += m_rotations[eType].m_aimAssist;
  412.  
  413.         delta = fmod(delta, gf_PI2);
  414.         if (delta > gf_PI)  delta -= gf_PI2;
  415.         if (delta < -gf_PI) delta += gf_PI2;
  416.  
  417.         Limit(delta, -max_rotation, max_rotation);
  418.  
  419.         Ang3 deltaAngles(ZERO);
  420.         if (eType == eVTRT_Pitch)
  421.                 deltaAngles.x = delta;
  422.         else if (eType == eVTRT_Yaw)
  423.                 deltaAngles.z = delta;
  424.         else
  425.                 CRY_ASSERT(false && "Unknown turret rotation");
  426.  
  427.         Matrix34 tm = pPart->GetLocalBaseTM();
  428.         Ang3 angles = Ang3::GetAnglesXYZ(tm) + deltaAngles;
  429.  
  430.         float lerp = 0.f;
  431.         if (eType == eVTRT_Pitch)
  432.         {
  433.                 Vec3 yAxis = m_rotations[eVTRT_Yaw].m_pPart->GetLocalBaseTM().GetColumn1();
  434.                 yAxis.z = 0.f;
  435.                 yAxis.normalize();
  436.                 lerp = 0.5f - 0.5f * yAxis.y;
  437.                 Limit(lerp, 0.0f, 1.0f);
  438.         }
  439.  
  440.         // clamp to limits
  441.         if (m_rotations[eType].m_minLimitF != 0.0f || m_rotations[eType].m_maxLimit != 0.0f)
  442.         {
  443.                 // Different clamp angles facing forwards/backwards
  444.                 float minLimit = m_rotations[eType].m_minLimitF + (m_rotations[eType].m_minLimitB - m_rotations[eType].m_minLimitF) * lerp;
  445.                 float angle = (eType == eVTRT_Pitch) ? angles.x : angles.z;
  446.                 if (angle > m_rotations[eType].m_maxLimit || angle < minLimit)
  447.                 {
  448.                         angle = clamp_tpl(angle, minLimit, m_rotations[eType].m_maxLimit);
  449.                         m_rotations[eType].m_currentValue = 0.f;
  450.  
  451.                         if (eType == eVTRT_Pitch)
  452.                                 angles.x = angle;
  453.                         else
  454.                                 angles.z = angle;
  455.                 }
  456.         }
  457.  
  458.         m_rotations[eType].m_orientation.Set(Quat::CreateRotationXYZ(angles));
  459.         m_rotations[eType].m_orientation.Update(frameTime);
  460.  
  461.         m_rotations[eType].m_action = 0.0f;
  462.         m_rotations[eType].m_aimAssist = 0.0f;
  463.  
  464.         Matrix34 newTM(m_rotations[eType].m_orientation.Get().GetNormalized());
  465.         newTM.SetTranslation(tm.GetTranslation());
  466.         pPart->SetLocalBaseTM(newTM);
  467.  
  468.         // store world-space rotation
  469.         const Matrix34& worldTM = pPart->GetWorldTM();
  470.         m_rotations[eType].m_prevWorldQuat = Quat(worldTM);
  471.         CRY_ASSERT(m_rotations[eType].m_prevWorldQuat.IsValid());
  472.  
  473.         // now update the turret sound based on the calculated rotation speed
  474.         UpdateRotationSound(eType, delta, frameTime);
  475.  
  476. }
  477.  
  478. //------------------------------------------------------------------------
  479. void CVehicleSeatActionRotateTurret::SetAimGoal(Vec3 aimPos, int priority)
  480. {
  481.         if (m_aimGoalPriority <= priority)
  482.         {
  483.                 m_aimGoal = aimPos;
  484.                 m_aimGoalPriority = priority;
  485.         }
  486. }
  487.  
  488. //------------------------------------------------------------------------
  489. bool CVehicleSeatActionRotateTurret::GetRemainingAnglesToAimGoalInDegrees(float& pitch, float& yaw)
  490. {
  491.         // no aim goal set (or it got cleared)?
  492.         if (m_aimGoal.IsZero())
  493.         {
  494.                 return false; // have no aim goal
  495.         }
  496.  
  497.         IVehiclePart* pPitchPart = m_rotations[eVTRT_Pitch].m_pPart;
  498.         IVehiclePart* pYawPart = m_rotations[eVTRT_Yaw].m_pPart;
  499.  
  500.         if (!pYawPart)
  501.         {
  502.                 pitch = yaw = 0.0f;
  503.                 return true;  // have an aim goal
  504.         }
  505.  
  506.         // aim goal is a world pos. Convert it to vehicle space:
  507.         Vec3 aimGoalLocal = m_pVehicle->GetEntity()->GetWorldTM().GetInverted() * m_aimGoal;
  508.  
  509.         // direction from yaw part pivot to aim goal
  510.         Vec3 yawPartToAimGoal = aimGoalLocal - pYawPart->GetLocalTM(false).GetTranslation();
  511.  
  512.         // angles from yaw part to aim goal
  513.         Quat aimDir = Quat::CreateRotationVDir(yawPartToAimGoal.GetNormalizedSafe());
  514.         Ang3 desiredAngles(aimDir);
  515.  
  516.         if (pPitchPart)
  517.         {
  518.                 Ang3 pitchAngles(pPitchPart->GetLocalTM(false));
  519.                 pitch = RAD2DEG(desiredAngles.x - pitchAngles.x);
  520.                 pitch = fmod(pitch, 360.0f);
  521.         }
  522.         else
  523.         {
  524.                 pitch = 0.0f;
  525.         }
  526.  
  527.         Ang3 yawAngles(pYawPart->GetLocalTM(false));
  528.         yaw = RAD2DEG(desiredAngles.z - yawAngles.z);
  529.         yaw = fmod(yaw, 360.0f);
  530.  
  531.         return true;  // have an aim goal
  532. }
  533.  
  534. //------------------------------------------------------------------------
  535. float CVehicleSeatActionRotateTurret::GetDamageSpeedMul(CVehiclePartBase* pPart)
  536. {
  537.         // slowdown by max 50%, starting from 75% damage
  538.         return 1.0f - 2.f * max(min(1.f, pPart->m_damageRatio) - 0.75f, 0.f);
  539. }
  540.  
  541. //------------------------------------------------------------------------
  542. bool CVehicleSeatActionRotateTurret::InitRotation(IVehicle* pVehicle, const CVehicleParams& rotationTable, EVehicleTurretRotationType eType)
  543. {
  544.         if (rotationTable)
  545.         {
  546.                 if (rotationTable.haveAttr("part"))
  547.                         m_rotations[eType].m_pPart = static_cast<CVehiclePartBase*>(m_pVehicle->GetPart(rotationTable.getAttr("part")));
  548.  
  549.                 if (rotationTable.getAttr("speed", m_rotations[eType].m_speed) && m_rotations[eType].m_pPart)
  550.                 {
  551.                         m_rotations[eType].m_pPart->SetMoveable();
  552.  
  553.                         rotationTable.getAttr("accel", m_rotations[eType].m_acceleration);
  554.  
  555.                         if (CVehicleParams limitsTable = rotationTable.findChild("Limits"))
  556.                         {
  557.                                 // Forward facing limits
  558.                                 if (limitsTable.getChildCount() >= 2)
  559.                                 {
  560.                                         if (CVehicleParams limitRef = limitsTable.getChild(0))
  561.                                                 m_rotations[eType].m_minLimitF = (float)DEG2RAD((float)atof(limitRef.getAttr("value")));
  562.                                         else
  563.                                                 m_rotations[eType].m_minLimitF = 0.0f;
  564.  
  565.                                         if (CVehicleParams limitRef = limitsTable.getChild(1))
  566.                                                 m_rotations[eType].m_maxLimit = (float)DEG2RAD((float)atof(limitRef.getAttr("value")));
  567.                                         else
  568.                                                 m_rotations[eType].m_maxLimit = 0.0f;
  569.                                 }
  570.  
  571.                                 // Backwards facing limits
  572.                                 m_rotations[eType].m_minLimitB = m_rotations[eType].m_minLimitF;
  573.                                 if (limitsTable.getChildCount() >= 3)
  574.                                 {
  575.                                         if (CVehicleParams limitRef = limitsTable.getChild(2))
  576.                                                 m_rotations[eType].m_minLimitB = (float)DEG2RAD((float)atof(limitRef.getAttr("value")));
  577.                                 }
  578.                         }
  579.                 }
  580.                 rotationTable.getAttr("worldSpace", m_rotations[eType].m_worldSpace);
  581.         }
  582.  
  583.         return true;
  584. }
  585.  
  586. //------------------------------------------------------------------------
  587. bool CVehicleSeatActionRotateTurret::InitRotationSounds(const CVehicleParams& rotationParams, EVehicleTurretRotationType eType)
  588. {
  589.         CVehicleParams sound = rotationParams.findChild("Sound");
  590.         if (!sound)
  591.                 return false;
  592.  
  593.         if (sound.haveAttr("event"))
  594.         {
  595.                 if (string helperName = sound.getAttr("helper"))
  596.                 {
  597.                         if (IVehicleHelper* pHelper = m_pVehicle->GetHelper(helperName))
  598.                         {
  599.                                 SVehicleSoundInfo info;
  600.                                 info.name = sound.getAttr("event");
  601.                                 info.pHelper = pHelper;
  602.                                 m_rotations[eType].m_turnSoundId = m_pVehicle->AddSoundEvent(info);
  603.  
  604.                                 if (sound.haveAttr("eventDamage"))
  605.                                 {
  606.                                         SVehicleSoundInfo dmgInfo;
  607.                                         info.name = sound.getAttr("eventDamage");
  608.                                         info.pHelper = pHelper;
  609.                                         m_rotations[eType].m_damageSoundId = m_pVehicle->AddSoundEvent(info);
  610.                                 }
  611.  
  612.                                 return true;
  613.                         }
  614.                 }
  615.  
  616.                 return false;
  617.         }
  618.  
  619.         return true;
  620. }
  621.  
  622. //------------------------------------------------------------------------
  623. void CVehicleSeatActionRotateTurret::UpdateRotationSound(EVehicleTurretRotationType type, float speed, float deltaTime)
  624. {
  625.         // update rotation sound, if available
  626.         if (m_rotations[type].m_turnSoundId == InvalidSoundEventId)
  627.                 return;
  628.  
  629.         if (!m_pVehicle->IsPlayerDriving() && !m_pVehicle->IsPlayerPassenger())
  630.                 return;
  631.  
  632.         const static float minSpeed = 0.0002f;
  633.         const static float soundDamageRatio = 0.2f;
  634.  
  635.         speed *= GetDamageSpeedMul(m_rotations[type].m_pPart);
  636.  
  637.         bool bDamage = m_rotations[type].m_pPart->m_damageRatio > soundDamageRatio && m_pVehicle->IsPlayerPassenger();
  638.  
  639.         if (speed != m_rotations[type].m_relSpeed)
  640.         {
  641.                 if ((fabsf(speed) < 1e-4) && (fabsf(m_rotations[type].m_relSpeed) < 1e-4))
  642.                 {
  643.                         m_rotations[type].m_relSpeed = 0.0f;
  644.                 }
  645.                 else
  646.                 {
  647.                         Interpolate(m_rotations[type].m_relSpeed, speed, 8.0f, deltaTime);
  648.                 }
  649.  
  650.                 float speedParam = (speed != 0.0f) ? min(1.0f, m_rotations[type].m_relSpeed / speed) : 0.0f;
  651.  
  652.                 m_pVehicle->SetSoundParam(m_rotations[type].m_turnSoundId, "speed", speedParam, true);
  653.  
  654.                 if (bDamage)
  655.                 {
  656.                         m_pVehicle->SetSoundParam(m_rotations[type].m_damageSoundId, "speed", speedParam, true);
  657.                 }
  658.  
  659.                 if (fabsf(m_rotations[type].m_relSpeed) < minSpeed)
  660.                 {
  661.                         m_pVehicle->StopSound(m_rotations[type].m_turnSoundId);
  662.                         m_pVehicle->StopSound(m_rotations[type].m_damageSoundId);
  663.                 }
  664.         }
  665.  
  666.         float inout = 1.f;
  667.         if (m_pVehicle->IsPlayerPassenger())
  668.         {
  669.                 if (IVehicleSeat* pSeat = m_pVehicle->GetSeatForPassenger(CCryAction::GetCryAction()->GetClientActor()->GetEntityId()))
  670.                 {
  671.                         if (IVehicleView* pView = pSeat->GetCurrentView())
  672.                         {
  673.                                 if (!pView->IsThirdPerson())
  674.                                         inout = pSeat->GetSoundParams().inout;
  675.                         }
  676.                 }
  677.         }
  678.  
  679.         REINST("update params");
  680.         /*if (ISound* pSound = m_pVehicle->GetSound(m_rotations[type].m_turnSoundId, false))
  681.            pSound->SetParam("in_out", inout, false);
  682.  
  683.            if (bDamage)
  684.            {
  685.            if (ISound* pSound = m_pVehicle->GetSound(m_rotations[type].m_damageSoundId, false))
  686.            {
  687.             pSound->SetParam("in_out", inout, false);
  688.             pSound->SetParam("damage", min(1.f, m_rotations[type].m_pPart->m_damageRatio), false);
  689.            }
  690.            } */
  691. }
  692.  
  693. //------------------------------------------------------------------------
  694. bool CVehicleSeatActionRotateTurret::GetRotationLimits(int axis, float& min, float& max)
  695. {
  696.         EVehicleTurretRotationType type;
  697.         if (axis == 0)
  698.                 type = eVTRT_Pitch;
  699.         else if (axis == 2)
  700.                 type = eVTRT_Yaw;
  701.         else
  702.                 return false;
  703.  
  704.         min = m_rotations[type].m_minLimitF;
  705.         max = m_rotations[type].m_maxLimit;
  706.         return true;
  707. }
  708.  
  709. DEFINE_VEHICLEOBJECT(CVehicleSeatActionRotateTurret);
  710.  
downloadVehicleSeatActionRotateTurret.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top