BVB Source Codes

CRYENGINE Show VehicleSeat.cpp Source code

Return Download CRYENGINE: download VehicleSeat.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 standard seat for vehicles
  8.  
  9.    -------------------------------------------------------------------------
  10.    History:
  11.    - 14:04:2005: Created by Mathieu Pinard
  12.  
  13. *************************************************************************/
  14. #include "StdAfx.h"
  15. #include "GameObjects/GameObject.h"
  16. #include "IActorSystem.h"
  17. #include "IAnimatedCharacter.h"
  18. #include "IVehicleSystem.h"
  19. #include "IViewSystem.h"
  20. #include "CryAction.h"
  21. #include "IItemSystem.h"
  22. #include <CryRenderer/IRenderAuxGeom.h>
  23. #include "IGameRulesSystem.h"
  24. #include "PersistantDebug.h"
  25. #include "CryActionCVars.h"
  26.  
  27. #include "VehicleSeat.h"
  28. #include "VehicleSeatGroup.h"
  29. #include "VehiclePartAnimated.h"
  30. #include "Vehicle.h"
  31.  
  32. #include "VehicleSeatActionMovement.h"
  33. #include "VehicleSeatActionRotateTurret.h"
  34. #include "VehicleSeatActionWeapons.h"
  35. #include "VehicleSeatSerializer.h"
  36. #include "VehicleViewThirdPerson.h"
  37. #include "VehicleUtils.h"
  38.  
  39. #include "../Network/GameContext.h"
  40. #include "../Network/GameChannel.h"
  41. #include "../Network/GameServerNub.h"
  42. #include "../Network/GameServerChannel.h"
  43.  
  44. #include <CryAISystem/IPathfinder.h>
  45. #include <CryAISystem/IAIActor.h>
  46. #include <CryAISystem/IAIObject.h>
  47.  
  48. #include "Animation/VehicleSeatAnimActions.h"
  49.  
  50. //#pragma optimize("", off)
  51. //#pragma inline_depth(0)
  52.  
  53. CCryAction* CVehicleSeat::m_pGameFramework = NULL;
  54.  
  55. //------------------------------------------------------------------------
  56. CVehicleSeat::CVehicleSeat()
  57.         : m_exitOffsetPlayer(ZERO)
  58.         , m_adjustedExitPos(ZERO)
  59.         , m_exitWorldPos(ZERO)
  60.         , m_pVehicle(nullptr)
  61.         , m_pSerializer(nullptr)
  62.         , m_pWeaponAction(nullptr)
  63.         , m_pTurretAction(nullptr)
  64.         , m_pSeatGroup(nullptr)
  65.         , m_pRemoteSeat(nullptr)
  66.         , m_pAimPart(nullptr)
  67.         , m_pEnterHelper(nullptr)
  68.         , m_pExitHelper(nullptr)
  69.         , m_pSitHelper(nullptr)
  70.         , m_pAIVisionHelper(nullptr)
  71.         , m_serializerId(0)
  72.         , m_passengerId(0)
  73.         , m_aiWeaponId(0)
  74.         , m_seatId(InvalidVehicleSeatId)
  75.         , m_currentView(InvalidVehicleViewId)
  76.         , m_lockStatus(eVSLS_Unlocked)
  77.         , m_lockDefault(eVSLS_Unlocked)
  78.         , m_pIdleAction(nullptr)
  79.         , m_postEnterId(0)
  80.         , m_postViewId(0)
  81.         , m_explosionShakeMult(1.0f)
  82.         , m_seatGroupIndex(1)
  83.         , m_transitionType(eVT_None)
  84.         , m_prevTransitionType(eVT_None)
  85.         , m_queuedTransition(eVT_None)
  86.         , m_isDriver(false)
  87.         , m_isPassengerShielded(false)
  88.         , m_isPassengerHidden(false)
  89.         , m_isPassengerExposed(false)
  90.         , m_isPlayerViewBlending(false)
  91.         , m_stopAllAnimationsOnEnter(true)
  92.         , m_skipViewBlending(false)
  93.         , m_updatePassengerTM(true)
  94.         , m_isRemoteControlled(false)
  95.         , m_isRagdollingOnDeath(false)
  96.         , m_movePassengerOnExit(true)
  97.         , m_autoAimEnabled(false)
  98.         , m_transformViewOnExit(true)
  99.         , m_shouldEnterInFirstPerson(true)
  100.         , m_shouldExitInFirstPerson(true)
  101. {}
  102.  
  103. //------------------------------------------------------------------------
  104. CVehicleSeat::~CVehicleSeat()
  105. {
  106.         CRY_ASSERT_MESSAGE(!m_passengerId, "Passenger should be long gone by now.");
  107.  
  108.         for (TVehicleSeatActionVector::iterator ite = m_seatActions.begin(); ite != m_seatActions.end(); ++ite)
  109.         {
  110.                 SSeatActionData& seatActionData = *ite;
  111.                 CRY_ASSERT(seatActionData.pSeatAction);
  112.                 PREFAST_ASSUME(seatActionData.pSeatAction);
  113.                 seatActionData.pSeatAction->Release();
  114.                 seatActionData.pSeatAction = NULL;
  115.         }
  116.  
  117.         for (TVehicleViewVector::iterator it = m_views.begin(); it != m_views.end(); ++it)
  118.                 (*it)->Release();
  119.  
  120.         if (gEnv->bMultiplayer && gEnv->bServer && gEnv->pEntitySystem->GetEntity(m_serializerId))
  121.         {
  122.                 gEnv->pEntitySystem->RemoveEntity(m_serializerId, true /*Remove Now*/);
  123.                 m_serializerId = 0;
  124.                 m_pSerializer = 0;
  125.         }
  126. }
  127.  
  128. namespace
  129. {
  130. template<typename T>
  131. T GetAttrWithDefault(const CVehicleParams& seatTable, const char* name, const T& def)
  132. {
  133.         T value = def;
  134.         seatTable.getAttr(name, value);
  135.         return value;
  136. }
  137. }
  138.  
  139. //------------------------------------------------------------------------
  140. bool CVehicleSeat::Init(IVehicle* pVehicle, TVehicleSeatId seatId, const CVehicleParams& seatTable)
  141. {
  142.         IVehicleSystem* pVehicleSystem = CCryAction::GetCryAction()->GetIVehicleSystem();
  143.  
  144.         if (!m_pGameFramework)
  145.         {
  146.                 m_pGameFramework = CCryAction::GetCryAction();
  147.         }
  148.  
  149.         m_pVehicle = (CVehicle*)pVehicle;
  150.         m_seatId = seatId;
  151.  
  152.         m_name = seatTable.getAttr("name");
  153.  
  154.         // Helpers
  155.         if (seatTable.haveAttr("sitHelper"))
  156.                 m_pSitHelper = m_pVehicle->GetHelper(seatTable.getAttr("sitHelper"));
  157.  
  158.         if (seatTable.haveAttr("aiVisionHelper"))
  159.                 m_pAIVisionHelper = m_pVehicle->GetHelper(seatTable.getAttr("aiVisionHelper"));
  160.  
  161.         if (seatTable.haveAttr("enterHelper"))
  162.                 m_pEnterHelper = m_pVehicle->GetHelper(seatTable.getAttr("enterHelper"));
  163.  
  164.         if (seatTable.haveAttr("exitHelper"))
  165.                 m_pExitHelper = m_pVehicle->GetHelper(seatTable.getAttr("exitHelper"));
  166.  
  167.         // Attributes
  168.         m_actionMap = seatTable.getAttr("actionMap");
  169.  
  170.         string lockedAttr = seatTable.getAttr("locked");
  171.         if (!lockedAttr.empty())
  172.         {
  173.                 if (lockedAttr == "All" || lockedAttr == "1")
  174.                         m_lockStatus = eVSLS_Locked;
  175.                 else if (lockedAttr == "AI")
  176.                         m_lockStatus = eVSLS_LockedForAI;
  177.                 else if (lockedAttr == "Players")
  178.                         m_lockStatus = eVSLS_LockedForPlayers;
  179.                 else
  180.                         m_lockStatus = eVSLS_Unlocked;
  181.         }
  182.         m_lockDefault = m_lockStatus;
  183.  
  184.         m_autoAimEnabled = GetAttrWithDefault<bool>(seatTable, "AutoAim", m_autoAimEnabled);
  185.         if (seatTable.haveAttr("AimPart"))
  186.                 m_pAimPart = m_pVehicle->GetPart(seatTable.getAttr("AimPart"));
  187.  
  188.         // Enter/exit settings
  189.         m_transformViewOnExit = GetAttrWithDefault<bool>(seatTable, "TransformViewOnExit", m_transformViewOnExit);
  190.         m_shouldEnterInFirstPerson = GetAttrWithDefault<bool>(seatTable, "enterInFirstPerson", m_shouldEnterInFirstPerson);
  191.         m_shouldExitInFirstPerson = GetAttrWithDefault<bool>(seatTable, "exitInFirstPerson", m_shouldExitInFirstPerson);
  192.         m_movePassengerOnExit = GetAttrWithDefault<bool>(seatTable, "movePassengerOnExit", m_movePassengerOnExit);
  193.         m_isRagdollingOnDeath = GetAttrWithDefault<bool>(seatTable, "ragdollOnDeath", m_isRagdollingOnDeath);
  194.         m_stopAllAnimationsOnEnter = !GetAttrWithDefault<bool>(seatTable, "disableStopAllAnimationsOnEnter", m_stopAllAnimationsOnEnter);
  195.         m_exitOffsetPlayer = GetAttrWithDefault<Vec3>(seatTable, "exitOffsetPlayer", m_exitOffsetPlayer);
  196.         m_seatNameToUseForEntering = seatTable.getAttr("usesSeatForEntering");
  197.  
  198.         m_updatePassengerTM = GetAttrWithDefault<bool>(seatTable, "updatePassengerTM", m_updatePassengerTM);
  199.  
  200.         m_isDriver = GetAttrWithDefault<bool>(seatTable, "isDriver", m_isDriver);
  201.         m_isRemoteControlled = GetAttrWithDefault<bool>(seatTable, "isRemoteControlled", m_isRemoteControlled);
  202.         m_isPassengerShielded = GetAttrWithDefault<bool>(seatTable, "isPassengerShielded", m_isPassengerShielded);
  203.         m_isPassengerExposed = GetAttrWithDefault<bool>(seatTable, "isPassengerExposed", m_isPassengerExposed);
  204.         m_isPassengerHidden = GetAttrWithDefault<bool>(seatTable, "isPassengerHidden", m_isPassengerHidden);
  205.  
  206.         m_useActionsRemotelyOfSeat = seatTable.getAttr("remotelyUseActionsFromSeat");
  207.         m_explosionShakeMult = GetAttrWithDefault<float>(seatTable, "explosionShakeMult", m_explosionShakeMult);
  208.  
  209.         // Seat Group
  210.         m_seatGroupIndex = GetAttrWithDefault<int>(seatTable, "seatGroupIndex", m_seatGroupIndex);
  211.  
  212.         // Mannequin
  213.         IActionController* pActionController = m_pVehicle->GetAnimationComponent().GetActionController();
  214.         if (pActionController != NULL)
  215.         {
  216.                 const char* actionNames[eMannequinSeatAction_Count] = { "Idle", "ExitDoor" };
  217.                 const SControllerDef& controllerDef = pActionController->GetContext().controllerDef;
  218.  
  219.                 // Set defaults
  220.                 for (int i = 0; i < eMannequinSeatAction_Count; ++i)
  221.                 {
  222.                         stack_string fragmentName = actionNames[i];
  223.                         fragmentName.append(GetName().c_str());
  224.  
  225.                         m_seatFragmentIDs[i] = controllerDef.m_fragmentIDs.Find(fragmentName.c_str());
  226.                 }
  227.  
  228.                 // Override with custom values
  229.                 if (CVehicleParams mannequinTable = seatTable.findChild("Mannequin"))
  230.                 {
  231.                         for (int i = 0; i < eMannequinSeatAction_Count; ++i)
  232.                         {
  233.                                 if (mannequinTable.haveAttr(actionNames[i]))
  234.                                 {
  235.                                         m_seatFragmentIDs[i] = controllerDef.m_fragmentIDs.Find(mannequinTable.getAttr(actionNames[i]));
  236.                                 }
  237.                         }
  238.                 }
  239.         }
  240.  
  241.         // Views
  242.         if (CVehicleParams viewsTable = seatTable.findChild("Views"))
  243.         {
  244.                 int viewCount = viewsTable.getChildCount();
  245.                 m_views.reserve(viewCount);
  246.                 for (int i = 0; i < viewCount; ++i)
  247.                 {
  248.                         if (CVehicleParams viewTable = viewsTable.getChild(i))
  249.                         {
  250.                                 string className = viewTable.getAttr("class");
  251.                                 if (!className.empty())
  252.                                 {
  253.                                         if (CVehicleParams viewParamsTable = viewTable.findChild(className))
  254.                                         {
  255.                                                 IVehicleView* view = pVehicleSystem->CreateVehicleView(className);
  256.                                                 if (view)
  257.                                                 {
  258.                                                         if (view->Init(this, viewTable))
  259.                                                                 m_views.push_back(view);
  260.                                                         else
  261.                                                                 delete view;
  262.                                                 }
  263.                                         }
  264.                                 }
  265.                         }
  266.                 }
  267.         }
  268.  
  269.         // Sounds
  270.         if (CVehicleParams soundsTable = seatTable.findChild("Sounds"))
  271.         {
  272.                 soundsTable.getAttr("inout", m_soundParams.inout);
  273.                 soundsTable.getAttr("mood", m_soundParams.mood);
  274.                 const char* moodName = soundsTable.getAttr("moodName");
  275.                 if (moodName && moodName[0])
  276.                 {
  277.                         m_soundParams.moodName = moodName;
  278.                 }
  279.         }
  280.  
  281.         // Actions
  282.         InitSeatActions(seatTable);
  283.  
  284.         return true;
  285. }
  286.  
  287. //------------------------------------------------------------------------
  288. void CVehicleSeat::PostInit(IVehicle* pVehicle)
  289. {
  290.         if (!m_useActionsRemotelyOfSeat.empty())
  291.         {
  292.                 TVehicleSeatId seatId = m_pVehicle->GetSeatId(m_useActionsRemotelyOfSeat.c_str());
  293.  
  294.                 if (seatId != InvalidVehicleSeatId)
  295.                         m_pRemoteSeat = (CVehicleSeat*)m_pVehicle->GetSeatById(seatId);
  296.  
  297.                 m_useActionsRemotelyOfSeat.clear();
  298.         }
  299. }
  300.  
  301. //------------------------------------------------------------------------
  302. void CVehicleSeat::OnSpawnComplete()
  303. {
  304.  
  305.         bool needsSynch = !m_seatActions.empty();
  306.  
  307.         if (gEnv->bMultiplayer && gEnv->bServer && needsSynch && !IsDemoPlayback() && !(m_pVehicle->GetEntity()->GetFlags() & ENTITY_FLAG_CLIENT_ONLY))
  308.         {
  309.                 string name(m_pVehicle->GetEntity()->GetName());
  310.                 name.append("_serializer_");
  311.  
  312.                 char a[128] = { 0 };
  313.                 name.append(ltoa(m_seatId, a, 10));
  314.  
  315.                 SEntitySpawnParams params;
  316.                 params.sName = name.c_str();
  317.                 params.nFlags = ENTITY_FLAG_NEVER_NETWORK_STATIC | ENTITY_FLAG_NO_SAVE;
  318.                 params.pClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("VehicleSeatSerializer");
  319.  
  320.                 if (!params.pClass)
  321.                 {
  322.                         CryFatalError("VehicleSeatSerializer not registered in the entity system!");
  323.                 }
  324.  
  325.                 static_cast<CVehicleSystem*>(CCryAction::GetCryAction()->GetIVehicleSystem())->SetInitializingSeat(this);
  326.  
  327.                 IEntity* pSerializerEntity = gEnv->pEntitySystem->SpawnEntity(params);
  328.  
  329.                 static_cast<CVehicleSystem*>(CCryAction::GetCryAction()->GetIVehicleSystem())->SetInitializingSeat(0);
  330.  
  331.                 CGameObject* pSerializerGameObject = (CGameObject*)pSerializerEntity->GetProxy(ENTITY_PROXY_USER);
  332.         }
  333.  
  334.         for (TVehicleSeatActionVector::iterator it = m_seatActions.begin(), end = m_seatActions.end(); it != end; ++it)
  335.         {
  336.                 SSeatActionData& data = *it;
  337.                 if (data.pSeatAction)
  338.                         data.pSeatAction->OnSpawnComplete();
  339.         }
  340. }
  341.  
  342. //------------------------------------------------------------------------
  343. bool CVehicleSeat::InitSeatActions(const CVehicleParams& seatTable)
  344. {
  345.         if (IsDriver())
  346.         {
  347.                 CVehicleSeatActionMovement* pActionMovement = new CVehicleSeatActionMovement;
  348.                 if (pActionMovement && pActionMovement->Init(m_pVehicle, this))
  349.                 {
  350.                         m_seatActions.resize(m_seatActions.size() + 1);
  351.                         SSeatActionData& seatActionData = m_seatActions.back();
  352.  
  353.                         seatActionData.pSeatAction = pActionMovement;
  354.                         seatActionData.isAvailableRemotely = true;
  355.                 }
  356.                 else
  357.                 {
  358.                         CRY_ASSERT(0 && "[CVehicleSeat::InitSeatActions] failed to init movement action");
  359.                         delete pActionMovement;
  360.                 }
  361.         }
  362.  
  363.         IVehicleSystem* pVehicleSystem = CCryAction::GetCryAction()->GetIVehicleSystem();
  364.         CRY_ASSERT(pVehicleSystem);
  365.  
  366.         CVehicleParams seatActionsTable = seatTable.findChild("SeatActions");
  367.         if (!seatActionsTable)
  368.                 return false;
  369.  
  370.         int i = 0;
  371.         int c = seatActionsTable.getChildCount();
  372.  
  373.         for (; i < c; i++)
  374.         {
  375.                 if (CVehicleParams seatActionTable = seatActionsTable.getChild(i))
  376.                 {
  377.                         string className = seatActionTable.getAttr("class");
  378.                         if (!className.empty())
  379.                         {
  380.                                 IVehicleSeatAction* pSeatAction = pVehicleSystem->CreateVehicleSeatAction(className);
  381.                                 if (pSeatAction && pSeatAction->Init(m_pVehicle, this, seatActionTable))
  382.                                 {
  383.                                         pSeatAction->m_name = seatActionTable.getAttr("name");
  384.  
  385.                                         // add the seat action to the vector
  386.                                         m_seatActions.resize(m_seatActions.size() + 1);
  387.                                         SSeatActionData& seatActionData = m_seatActions.back();
  388.  
  389.                                         seatActionData.pSeatAction = pSeatAction;
  390.  
  391.                                         // store first weapon/turret action for quick access
  392.                                         CVehicleSeatActionWeapons* pActionWeapons = CAST_VEHICLEOBJECT(CVehicleSeatActionWeapons, pSeatAction);
  393.                                         if (pActionWeapons && !m_pWeaponAction)
  394.                                                 m_pWeaponAction = pActionWeapons;
  395.  
  396.                                         CVehicleSeatActionRotateTurret* pActionTurret = CAST_VEHICLEOBJECT(CVehicleSeatActionRotateTurret, pSeatAction);
  397.                                         if (pActionTurret && !m_pTurretAction)
  398.                                                 m_pTurretAction = pActionTurret;
  399.  
  400.                                         if (!seatActionTable.getAttr("isAvailableRemotely", seatActionData.isAvailableRemotely))
  401.                                                 seatActionData.isAvailableRemotely = false;
  402.                                 }
  403.                                 else
  404.                                 {
  405.                                         SAFE_RELEASE(pSeatAction);
  406.                                 }
  407.                         }
  408.                 }
  409.         }
  410.  
  411.         return true;
  412. }
  413.  
  414. //------------------------------------------------------------------------
  415. void CVehicleSeat::Reset()
  416. {
  417.         if (m_passengerId)
  418.                 Exit(false, true);
  419.  
  420.         for (TVehicleSeatActionVector::iterator it = m_seatActions.begin(), end = m_seatActions.end(); it != end; ++it)
  421.         {
  422.                 SSeatActionData& data = *it;
  423.                 data.Reset();
  424.         }
  425.  
  426.         if (IVehicleView* pView = GetCurrentView())
  427.                 pView->Reset();
  428.  
  429.         m_transitionType = eVT_None;
  430.         m_queuedTransition = eVT_None;
  431.  
  432.         m_lockStatus = m_lockDefault;
  433.         m_passengerId = 0;
  434.  
  435.         CHANGED_NETWORK_STATE(m_pVehicle, CVehicle::ASPECT_SEAT_PASSENGER);
  436. }
  437.  
  438. //------------------------------------------------------------------------
  439. void CVehicleSeat::SerializeActions(TSerialize ser, EEntityAspects aspects)
  440. {
  441.         for (TVehicleSeatActionVector::iterator it = m_seatActions.begin(); it != m_seatActions.end(); ++it)
  442.                 it->Serialize(ser, aspects);
  443. }
  444.  
  445. //------------------------------------------------------------------------
  446. bool CVehicleSeat::Enter(EntityId actorId, bool isTransitionEnabled)
  447. {
  448.         if (m_pVehicle->IsDestroyed())
  449.                 return false;
  450.  
  451.         if (gEnv->bMultiplayer && !CCryActionCVars::Get().g_multiplayerEnableVehicles)
  452.                 return false;
  453.  
  454.         IActorSystem* pActorSystem = CCryAction::GetCryAction()->GetIActorSystem();
  455.         CRY_ASSERT(pActorSystem);
  456.  
  457.         IActor* pActor = pActorSystem->GetActor(actorId);
  458.         if (!pActor)
  459.                 return false;
  460.  
  461.         const bool shouldEnslaveActor = ShouldEnslaveActorAnimations();
  462.  
  463.         if (pActor->IsPlayer())
  464.         {
  465.                 gEnv->pEntitySystem->RemoveEntityFromLayers(m_pVehicle->GetEntityId());
  466.         }
  467.  
  468.         if (IPhysicalEntity* pPE = m_pVehicle->GetEntity()->GetPhysics())
  469.         {
  470.                 pe_action_awake awakeParams;
  471.                 awakeParams.bAwake = true;
  472.                 pPE->Action(&awakeParams);
  473.         }
  474.  
  475.         if (!IsFree(pActor))
  476.         {
  477.                 if (m_passengerId != pActor->GetEntityId())
  478.                         return false;
  479.                 else if (m_transitionType == eVT_Entering && !m_postEnterId)
  480.                         return true;
  481.         }
  482.  
  483.         if (m_passengerId == pActor->GetEntityId() && m_transitionType == eVT_None && !m_postEnterId)
  484.                 return false;
  485.  
  486.         // exit previous seat if any
  487.         if (IVehicle* pPrevVehicle = pActor->GetLinkedVehicle())
  488.         {
  489.                 if (IVehicleSeat* pPrevSeat = pPrevVehicle->GetSeatForPassenger(pActor->GetEntityId()))
  490.                         if (pPrevSeat != this)
  491.                                 pPrevSeat->Exit(false, true);
  492.         }
  493.  
  494.         // in case there's just a corpse on the seat, we simply push it to the ground
  495.         if (m_passengerId && m_passengerId != pActor->GetEntityId())
  496.         {
  497.                 if (m_transitionType == eVT_RemoteUsage)
  498.                         ExitRemotely();
  499.  
  500.                 if (IActor* pCurrentPassenger = pActorSystem->GetActor(m_passengerId))
  501.                 {
  502.                         if (pCurrentPassenger->IsDead())
  503.                                 Exit(false);
  504.                         else
  505.                                 return false;
  506.                 }
  507.         }
  508.  
  509.         CVehicleAnimationComponent& animationComponent = m_pVehicle->GetAnimationComponent();
  510.         IActionController* pActionController = animationComponent.GetActionController();
  511.         bool doTransition = shouldEnslaveActor && isTransitionEnabled && (VehicleCVars().v_transitionAnimations == 1) && !IsRemoteControlledInternal() && (!pActor->IsPlayer() || (VehicleCVars().v_playerTransitions == 1)) && pActionController;
  512.         const SControllerDef* pContDef = NULL;
  513.  
  514.         if (pActionController && shouldEnslaveActor)
  515.         {
  516.                 animationComponent.AttachPassengerScope(this, actorId, true);
  517.                 pContDef = &pActionController->GetContext().controllerDef;
  518.         }
  519.  
  520.         // Start Animation if needed.
  521.         if (doTransition)
  522.         {
  523.                 pActor->HolsterItem(true);
  524.  
  525.                 m_transitionType = eVT_Entering;
  526.  
  527.                 m_aiWeaponId = 0;
  528.  
  529.                 SActorTargetParams target;
  530.                 CVehicleSeat* pSeatToEnter = NULL;
  531.  
  532.                 if (!m_seatNameToUseForEntering.empty())
  533.                 {
  534.                         pSeatToEnter = (CVehicleSeat*)m_pVehicle->GetSeatById(m_pVehicle->GetSeatId(m_seatNameToUseForEntering));
  535.                         if (pSeatToEnter)
  536.                         {
  537.                                 if (!pSeatToEnter->IsFree(pActor))
  538.                                         return false;
  539.  
  540.                                 pSeatToEnter->m_transitionType = eVT_SeatIsBorrowed;
  541.                         }
  542.                 }
  543.  
  544.                 if (!pSeatToEnter)
  545.                         pSeatToEnter = this;
  546.  
  547.                 // Transition Animation.
  548.                 int seatID = pSeatToEnter->GetSeatId();
  549.                 stack_string fragmentName = "EnterDoor";
  550.                 fragmentName.append(pSeatToEnter->GetName().c_str());
  551.                 FragmentID fragID = pContDef->m_fragmentIDs.Find(fragmentName.c_str());
  552.                 CVehicleSeatAnimActionEnter* enterAction = new CVehicleSeatAnimActionEnter(IVehicleAnimationComponent::ePriority_SeatTransition, fragID, this);
  553.                 QuatT targetPos(m_pVehicle->GetEntity()->GetPos(), m_pVehicle->GetEntity()->GetRotation());
  554.                 enterAction->SetParam("TargetPos", targetPos);
  555.                 pActionController->Queue(*enterAction);
  556.         }
  557.  
  558.         CryLog("[VEHICLE] [%s] ENTERING VEHICLE: Vehicle[%u] Passenger[%u]", gEnv->bServer ? "SERVER" : "CLIENT", m_pVehicle->GetEntityId(), actorId);
  559.  
  560.         // Link to Vehicle.
  561.         m_passengerId = actorId;
  562.         pActor->LinkToVehicle(m_pVehicle->GetEntityId());
  563.         CHANGED_NETWORK_STATE(m_pVehicle, CVehicle::ASPECT_SEAT_PASSENGER);
  564.  
  565.         if (!doTransition)
  566.         {
  567.                 if (!IsRemoteControlledInternal())
  568.                 {
  569.                         if (pActor->IsClient())
  570.                         {
  571.                                 EntityId currentItemId = 0;
  572.                                 IInventory* pInventory = pActor->GetInventory();
  573.                                 if (pInventory)
  574.                                         currentItemId = pInventory->GetCurrentItem();
  575.  
  576.                                 pActor->HolsterItem(true);
  577.  
  578.                                 if (pInventory)
  579.                                         pInventory->SetLastItem(currentItemId);
  580.                         }
  581.                         else
  582.                         {
  583.                                 pActor->HolsterItem(true);
  584.                         }
  585.                 }
  586.  
  587.                 if (pActor->IsPlayer() && !m_postEnterId)
  588.                 {
  589.                         if (m_stopAllAnimationsOnEnter && !IsRemoteControlledInternal())
  590.                         {
  591.                                 if (ICharacterInstance* pCharInstance = pActor->GetEntity()->GetCharacter(0))
  592.                                         pCharInstance->GetISkeletonAnim()->StopAnimationsAllLayers();
  593.                         }
  594.  
  595.                         m_isPlayerViewBlending = (isTransitionEnabled && VehicleCVars().v_transitionAnimations == 1) && pActionController;
  596.                 }
  597.  
  598.                 SitDown();
  599.         }
  600.  
  601.         // adjust the vehicle update slot to start calling the seat update function
  602.         m_pVehicle->GetGameObject()->EnableUpdateSlot(m_pVehicle, IVehicle::eVUS_PassengerIn);
  603.  
  604.         if (gEnv->bMultiplayer && gEnv->bServer)
  605.                 m_pVehicle->KillAbandonedTimer();
  606.  
  607.         return true;
  608. }
  609.  
  610. //------------------------------------------------------------------------
  611. bool CVehicleSeat::EnterRemotely(EntityId actorId)
  612. {
  613.         if (m_passengerId != 0 && actorId != m_passengerId && m_transitionType != eVT_Dying)
  614.                 return false;
  615.  
  616.         IActor* pActor = CCryAction::GetCryAction()->GetIActorSystem()->GetActor(actorId);
  617.         if (!(pActor && pActor->IsPlayer()))
  618.                 return false;
  619.  
  620.         m_passengerId = actorId;
  621.         m_transitionType = eVT_RemoteUsage;
  622.  
  623.         GivesActorSeatFeatures(true, true);
  624.  
  625.         CHANGED_NETWORK_STATE(m_pVehicle, CVehicle::ASPECT_SEAT_PASSENGER);
  626.  
  627.         return true;
  628. }
  629.  
  630. //------------------------------------------------------------------------
  631. bool CVehicleSeat::ExitRemotely()
  632. {
  633.         if (m_passengerId == 0 || m_transitionType != eVT_RemoteUsage)
  634.                 return false;
  635.  
  636.         GivesActorSeatFeatures(false, true);
  637.  
  638.         m_passengerId = 0;
  639.         CHANGED_NETWORK_STATE(m_pVehicle, CVehicle::ASPECT_SEAT_PASSENGER);
  640.  
  641.         m_transitionType = eVT_None;
  642.  
  643.         return true;
  644. }
  645.  
  646. //------------------------------------------------------------------------
  647. CVehicleSeat* CVehicleSeat::GetSeatUsedRemotely(bool onlyIfBeingUsed) const
  648. {
  649.         if (m_pRemoteSeat)
  650.         {
  651.                 if (onlyIfBeingUsed)
  652.                 {
  653.                         if (m_pRemoteSeat->GetCurrentTransition() != eVT_RemoteUsage || m_pRemoteSeat->GetPassenger(true) != m_passengerId)
  654.                                 return NULL;
  655.                 }
  656.  
  657.                 if (VehicleCVars().v_driverControlledMountedGuns == 0 && IsDriver() && m_pRemoteSeat->IsGunner())
  658.                         return NULL;
  659.         }
  660.  
  661.         return m_pRemoteSeat;
  662. }
  663.  
  664. //------------------------------------------------------------------------
  665. bool CVehicleSeat::ShouldEnslaveActorAnimations() const
  666. {
  667.         return (m_pWeaponAction == NULL) || !m_pWeaponAction->IsMounted() || (m_pVehicle->GetAnimationComponent().GetActionController() != NULL);
  668. }
  669.  
  670. //------------------------------------------------------------------------
  671. bool CVehicleSeat::SitDown()
  672. {
  673.         IActorSystem* pActorSystem = CCryAction::GetCryAction()->GetIActorSystem();
  674.         IActor* pActor = pActorSystem->GetActor(m_passengerId);
  675.         if (!pActor)
  676.                 return false;
  677.  
  678.         if (pActor->IsPlayer() && (VehicleCVars().v_playerTransitions == 0))
  679.         {
  680.                 // Just for the player, we keep him in the entered state until the next frame.
  681.                 m_transitionType = eVT_Entering;
  682.         }
  683.         else
  684.         {
  685.                 m_transitionType = eVT_None;
  686.         }
  687.  
  688.         IAISystem* pAISystem = gEnv->pAISystem;
  689.         if (pAISystem && pAISystem->IsEnabled())
  690.         {
  691.                 pAISystem->GetSmartObjectManager()->AddSmartObjectState(pActor->GetEntity(), "InVehicle");
  692.         }
  693.  
  694.         IEntity* pPassengerEntity = pActor->GetEntity();
  695.  
  696.         // MR: moved this to before GiveActorSeatFeatures, as the latter sets the vehicle view,
  697.         // which needs the remote seat to check for potentially available remote views
  698.         if (CVehicleSeat* pSeat = GetSeatUsedRemotely(false))
  699.                 pSeat->EnterRemotely(m_passengerId);
  700.  
  701.         if (pActor->IsPlayer() || pActor->GetEntity()->GetAI())
  702.         {
  703.                 GivesActorSeatFeatures(true);
  704.         }
  705.         else if (!pActor->GetEntity()->GetAI())
  706.         {
  707.                 // enable the seat actions
  708.                 for (TVehicleSeatActionVector::iterator ite = m_seatActions.begin(); ite != m_seatActions.end(); ++ite)
  709.                 {
  710.                         SSeatActionData& seatActionData = *ite;
  711.  
  712.                         if (seatActionData.isEnabled)
  713.                                 seatActionData.pSeatAction->StartUsing(m_passengerId);
  714.                 }
  715.         }
  716.  
  717.         if (pActor->IsClient() && gEnv->pInput)
  718.                 gEnv->pInput->RetriggerKeyState();
  719.  
  720.         // allow lua side of the seat implementation to do its business
  721.         HSCRIPTFUNCTION scriptFunction(0);
  722.         if (IScriptTable* pScriptTable = m_pVehicle->GetEntity()->GetScriptTable())
  723.         {
  724.                 if (pScriptTable->GetValue("OnActorSitDown", scriptFunction))
  725.                 {
  726.                         CRY_ASSERT(scriptFunction);
  727.                         ScriptHandle passengerHandle(pPassengerEntity->GetId());
  728.                         IScriptSystem* pIScriptSystem = gEnv->pScriptSystem;
  729.                         Script::Call(pIScriptSystem, scriptFunction, pScriptTable, GetSeatId(), passengerHandle);
  730.                         pIScriptSystem->ReleaseFunc(scriptFunction);
  731.                 }
  732.         }
  733.  
  734.         // broadcast an event about the situation
  735.         SVehicleEventParams eventParams;
  736.         eventParams.iParam = m_seatId;
  737.         eventParams.entityId = m_passengerId;
  738.         m_pVehicle->BroadcastVehicleEvent(eVE_PassengerEnter, eventParams);
  739.  
  740.         CHANGED_NETWORK_STATE(m_pVehicle, CVehicle::ASPECT_SEAT_PASSENGER);
  741.  
  742.         if (pActor->IsClient())
  743.         {
  744.                 if (IVehicleMovement* pMovement = m_pVehicle->GetMovement())
  745.                 {
  746.                         SVehicleMovementEventParams params;
  747.                         params.bValue = true;
  748.                         pMovement->OnEvent(IVehicleMovement::eVME_PlayerEnterLeaveVehicle, params);
  749.                 }
  750.         }
  751.  
  752.         UpdatePassengerLocalTM(pActor);
  753.  
  754.         if (m_pSeatGroup)
  755.                 m_pSeatGroup->OnPassengerEnter(this, m_passengerId);
  756.  
  757.         CCryAction::GetCryAction()->GetIGameplayRecorder()->Event(pActor->GetEntity(), GameplayEvent(eGE_EnteredVehicle, 0, 0, (void*)(EXPAND_PTR)m_pVehicle->GetEntityId()));
  758.  
  759.         return true;
  760. }
  761.  
  762. //------------------------------------------------------------------------
  763. bool CVehicleSeat::QueueTransition()
  764. {
  765.         // check if transition is prohibited by other blocking seats
  766.         const STransitionInfo& info = m_pVehicle->GetTransitionInfoForSeat(m_seatId);
  767.  
  768.         if (!info.waitFor.empty())
  769.         {
  770.                 for (int i = 0, nWait = info.waitFor.size(); i < nWait; ++i)
  771.                 {
  772.                         CVehicleSeat* pSeat = (CVehicleSeat*)m_pVehicle->GetSeatById(info.waitFor[i]);
  773.                         CRY_ASSERT(pSeat);
  774.  
  775.                         int trans = pSeat->GetCurrentTransition();
  776.  
  777.                         if (trans == eVT_Entering || trans == eVT_Exiting)
  778.                                 return true;
  779.                 }
  780.         }
  781.  
  782.         return false;
  783. }
  784.  
  785. //------------------------------------------------------------------------
  786. bool CVehicleSeat::Exit(bool isTransitionEnabled, bool force /*=false*/, Vec3 exitPos /*=ZERO*/)
  787. {
  788.         if (m_transitionType == eVT_RemoteUsage)
  789.                 return ExitRemotely();
  790.  
  791.         IActorSystem* pActorSystem = CCryAction::GetCryAction()->GetIActorSystem();
  792.         IActor* pActor = pActorSystem->GetActor(m_passengerId);
  793.  
  794.         if (!exitPos.IsEquivalent(ZERO))
  795.                 m_exitWorldPos = exitPos;
  796.  
  797.         // check the player can exit the vehicle from somewhere...
  798.         // This just ensures that when we reach StandUp there will be a valid place to exit from.
  799.         // Changed this for MP: only local client should decide whether it can get out or not (since it
  800.         //      will also decide where to place itself).
  801.         if (pActor && pActor->IsClient() && exitPos.IsEquivalent(ZERO))
  802.         {
  803.                 Matrix34 worldTM = GetExitTM(pActor, false);
  804.                 m_exitWorldPos = worldTM.GetTranslation();
  805.                 EntityId blockerId = 0;
  806.                 bool canExit = TestExitPosition(pActor, m_exitWorldPos, &blockerId);
  807.  
  808.                 // if our own seat exit is blocked, ask the vehicle for a free one...
  809.                 if (!canExit && !force)
  810.                 {
  811.                         canExit = m_pVehicle->GetExitPositionForActor(pActor, m_exitWorldPos, false);
  812.                 }
  813.  
  814.                 if (!canExit && !force)
  815.                 {
  816.                         m_exitWorldPos.zero();
  817.                         return false;
  818.                 }
  819.         }
  820.  
  821.         const bool shouldEnslaveActor = ShouldEnslaveActorAnimations();
  822.         bool doTransition = shouldEnslaveActor && pActor && ((VehicleCVars().v_playerTransitions == 1) || !pActor->IsPlayer());
  823.  
  824.         if (pActor)
  825.         {
  826.                 if (doTransition)
  827.                 {
  828.                         if (isTransitionEnabled && !force)
  829.                         {
  830.                                 if (QueueTransition())
  831.                                 {
  832.                                         m_queuedTransition = eVT_Exiting;
  833.                                         return true;
  834.                                 }
  835.                         }
  836.  
  837.                         if (m_transitionType == eVT_Entering)
  838.                         {
  839.                                 // reset actor target request
  840.                                 /*                      IAIObject* pAIObject = pActor->GetEntity()->GetAI();
  841.                                    if ( pAIObject )
  842.                                    {
  843.                                    CAIProxy* pAIProxy = (CAIProxy*) pAIObject->GetProxy();
  844.                                    pAIProxy->SetActorTarget( this, NULL );
  845.                                    }*/
  846.                         }
  847.                         else if (m_transitionType == eVT_None)
  848.                         {
  849.                                 m_adjustedExitPos.zero();
  850.  
  851.                                 if (IAIObject* pAIObject = pActor->GetEntity()->GetAI())
  852.                                 {
  853.                                         Matrix34 worldTM = GetExitTM(pActor);
  854.                                         Vec3 adjustedPos;
  855.  
  856.                                         if (IAIPathAgent* aiactor = pAIObject->CastToIAIActor())
  857.                                         {
  858.                                                 if (aiactor->GetValidPositionNearby(worldTM.GetTranslation(), adjustedPos))
  859.                                                         if (worldTM.GetTranslation() != adjustedPos)
  860.                                                                 m_adjustedExitPos = adjustedPos;
  861.                                         }
  862.                                 }
  863.                         }
  864.                 }
  865.                 else
  866.                 {
  867.                         /*m_adjustedExitPos.zero();
  868.                            Matrix34 worldTM = GetExitTM(pActor);
  869.                            Vec3 pos = worldTM.GetTranslation();
  870.                            int i = 0;
  871.                            bool valid = false;
  872.  
  873.                            while (!valid)
  874.                            valid = TestExitPos(pActor, pos, i++);
  875.  
  876.                            if (pos != worldTM.GetTranslation())
  877.                            m_adjustedExitPos = pos;
  878.                          */
  879.                 }
  880.         }
  881.  
  882.         m_transitionType = pActor && (m_transitionType != eVT_Entering) && doTransition ? eVT_Exiting : eVT_None;
  883.         m_queuedTransition = eVT_None;
  884.  
  885.         GivesActorSeatFeatures(false);
  886.  
  887.         if (pActor)
  888.         {
  889.                 IActionController* pActionController = m_pVehicle->GetAnimationComponent().GetActionController();
  890.  
  891.                 if ((VehicleCVars().v_playerTransitions == 1) || !pActor->IsPlayer())
  892.                 {
  893.                         pActor->HolsterItem(false);
  894.                         if (m_transitionType == eVT_Exiting && pActionController)
  895.                         {
  896.                                 if (!isTransitionEnabled || force || IsDemoPlayback())
  897.                                 {
  898.                                         StandUp();
  899.                                 }
  900.                                 else if (m_seatFragmentIDs[eMannequinSeatAction_Exit] != FRAGMENT_ID_INVALID)
  901.                                 {
  902.                                         CVehicleSeatAnimActionExit* exitAction = new CVehicleSeatAnimActionExit(IVehicleAnimationComponent::ePriority_SeatTransition, m_seatFragmentIDs[eMannequinSeatAction_Exit], this);
  903.                                         QuatT targetPos(m_pVehicle->GetEntity()->GetPos(), m_pVehicle->GetEntity()->GetRotation());
  904.                                         exitAction->SetParam("TargetPos", targetPos);
  905.                                         pActionController->Queue(*exitAction);
  906.                                 }
  907.                         }
  908.                         else
  909.                         {
  910.                                 // FrancescoR: Not sure in which cases this is needed but atm when we are here
  911.                                 // we are exiting with a m_transitionType == eVT_None. We should probably move the
  912.                                 // passenger on exit to avoid that they exit inside the vehicle itself
  913.  
  914.                                 //bool temp = m_movePassengerOnExit;
  915.                                 //m_movePassengerOnExit = !doTransition;
  916.                                 StandUp();
  917.                                 //m_movePassengerOnExit = temp;
  918.                         }
  919.                 }
  920.                 else
  921.                 {
  922.                         StandUp();
  923.                 }
  924.  
  925.                 if (m_pSeatGroup)
  926.                         m_pSeatGroup->OnPassengerExit(this, m_passengerId);
  927.  
  928.                 if (!m_exitWorldPos.IsZero())
  929.                 {
  930.                         Matrix34 worldTM = pActor->GetEntity()->GetWorldTM();
  931.                         worldTM.SetTranslation(m_exitWorldPos);
  932.                         pActor->GetEntity()->SetWorldTM(worldTM);
  933.                 }
  934.         }
  935.  
  936.         m_adjustedExitPos.zero();
  937.  
  938.         if (pActor && pActor->IsClient())
  939.         {
  940.                 if (IVehicleMovement* pMovement = m_pVehicle->GetMovement())
  941.                 {
  942.                         SVehicleMovementEventParams params;
  943.                         params.bValue = false;
  944.                         pMovement->OnEvent(IVehicleMovement::eVME_PlayerEnterLeaveVehicle, params);
  945.                 }
  946.         }
  947.  
  948.         if (!pActor)
  949.         {
  950.                 // seems to be necessary - had a crash on sv_restart, possibly because the actor has already been
  951.                 //      deleted, so m_passenger id is never reset, so ~CVehicleSeat() tries to call Exit again. This ends up calling
  952.                 // m_pVehicle->IsEmpty() below on a half-destructed vehicle
  953.                 m_passengerId = 0;
  954.                 return true;
  955.         }
  956.  
  957.         if (gEnv->bMultiplayer && gEnv->bServer && m_pVehicle->IsEmpty())
  958.                 m_pVehicle->StartAbandonedTimer();
  959.  
  960.         return true;
  961. }
  962.  
  963. //------------------------------------------------------------------------
  964. bool CVehicleSeat::StandUp()
  965. {
  966.         if (m_passengerId == 0)
  967.                 return false;
  968.  
  969.         IActor* pActor = CCryAction::GetCryAction()->GetIActorSystem()->GetActor(m_passengerId);
  970.         if (!pActor)
  971.                 return false;
  972.  
  973.         const string actorTextDescription = pActor->GetEntity()->GetEntityTextDescription().c_str();
  974.         const string vehicleTextDescription = m_pVehicle->GetEntity()->GetEntityTextDescription().c_str();
  975.         CryLog("Making %s leave %s", actorTextDescription.c_str(), vehicleTextDescription.c_str());
  976.         INDENT_LOG_DURING_SCOPE();
  977.  
  978.         if ((VehicleCVars().v_playerTransitions == 1) && pActor->IsClient())
  979.         {
  980.                 if (GetCurrentViewId() != InvalidVehicleViewId)
  981.                         SetView(InvalidVehicleViewId);
  982.         }
  983.  
  984.         if (m_pVehicle->GetAnimationComponent().GetActionController())
  985.         {
  986.                 m_pVehicle->GetAnimationComponent().AttachPassengerScope(this, m_passengerId, false);
  987.         }
  988.  
  989.         IEntity* pPassengerEntity = pActor->GetEntity();
  990.  
  991.         IAISystem* pAISystem = gEnv->pAISystem;
  992.         if (pAISystem && pAISystem->IsEnabled())
  993.         {
  994.                 pAISystem->GetSmartObjectManager()->RemoveSmartObjectState(pActor->GetEntity(), "InVehicle");
  995.         }
  996.  
  997.         // allow lua side of the seat implementation to do its business
  998.         HSCRIPTFUNCTION scriptFunction(0);
  999.         if (IScriptTable* pScriptTable = m_pVehicle->GetEntity()->GetScriptTable())
  1000.         {
  1001.                 if (pScriptTable->GetValue("OnActorStandUp", scriptFunction))
  1002.                 {
  1003.                         CRY_ASSERT(scriptFunction);
  1004.                         ScriptHandle passengerHandle(pPassengerEntity->GetId());
  1005.                         IScriptSystem* pIScriptSystem = gEnv->pScriptSystem;
  1006.                         Script::Call(pIScriptSystem, scriptFunction, pScriptTable, passengerHandle, true);
  1007.                         pIScriptSystem->ReleaseFunc(scriptFunction);
  1008.                 }
  1009.         }
  1010.  
  1011.         CryLog("[VEHICLE] [%s] EXITING VEHICLE:  Vehicle[%u] Passenger[%u]", gEnv->bServer ? "SERVER" : "CLIENT", m_pVehicle->GetEntityId(), pActor->GetEntityId());
  1012.  
  1013.         pActor->LinkToVehicle(0);
  1014.         m_passengerId = 0;
  1015.  
  1016.         if (pActor->IsClient() && gEnv->pInput)
  1017.                 gEnv->pInput->RetriggerKeyState();
  1018.  
  1019.         // current world transform of passenger
  1020.         // we always want to use the rotational part of this
  1021.         // and we want to use the position if he played an exit animation
  1022.         Matrix34 passengerTM = pPassengerEntity->GetWorldTM();
  1023.         Vec3 exitPos = passengerTM.GetTranslation();
  1024.         // this only gets set to true if the world transform should really be updated
  1025.         bool dirtyPos = false;
  1026.  
  1027.         if (m_movePassengerOnExit)
  1028.         {
  1029.                 if (!m_adjustedExitPos.IsZero())
  1030.                 {
  1031.                         // something external is trying to adjust the exit position ... so we will just let it do it
  1032.                         exitPos = m_adjustedExitPos;
  1033.                         dirtyPos = true;
  1034.                 }
  1035.                 else
  1036.                 {
  1037.                         // ok, we get to choose the exit position ourselves
  1038.                         // we assume that the exit animation will get us reasonably close to the exit helper (0.5m)
  1039.                         // if not, we do a fallback teleport
  1040.                         // the teleport is there to solve two case
  1041.                         //              - we don't have an exit animation
  1042.                         //              - something messed up playing the exit animation
  1043.                         static float teleportDistanceSq = 0.25f;
  1044.  
  1045.                         // by this point m_exitWorldPos should be valid (non-zero)
  1046.                         if (m_exitWorldPos.GetLengthSquared() > 0.01f)
  1047.                         {
  1048.                                 exitPos = m_exitWorldPos;
  1049.                                 dirtyPos = true;
  1050.                         }
  1051.                         else
  1052.                         {
  1053.                                 // if not, fallback to the old method and just exit this seat
  1054.                                 Matrix34 exitHelperTM = GetExitTM(pActor);
  1055.                                 Vec3 delta = exitHelperTM.GetTranslation() - exitPos;
  1056.                                 if (delta.GetLengthSquared() > teleportDistanceSq)
  1057.                                 {
  1058.                                         // teleport
  1059.                                         exitPos = exitHelperTM.GetTranslation();
  1060.                                         dirtyPos = true;
  1061.                                 }
  1062.                         }
  1063.                 }
  1064.         }
  1065.  
  1066.         // sanity check the exit position
  1067.         {
  1068.                 float elevation = gEnv->p3DEngine->GetTerrainElevation(exitPos.x, exitPos.y);
  1069.  
  1070.                 if (exitPos.z < elevation && (elevation - exitPos.z) < 5.0f)
  1071.                 {
  1072.                         // we are under the terrain ... but this can be fine if we are inside a VisArea (e.g. a tunnel inside the terrain)
  1073.                         Vec3 vehiclePos = m_pVehicle->GetEntity()->GetWorldPos();
  1074.                         IVisArea* pVehicleVisArea = gEnv->p3DEngine->GetVisAreaFromPos(vehiclePos);
  1075.                         IVisArea* pExitVisArea = gEnv->p3DEngine->GetVisAreaFromPos(exitPos);
  1076.  
  1077.                         if (!(pVehicleVisArea && pExitVisArea))
  1078.                         {
  1079.                                 dirtyPos = true;
  1080.                                 exitPos.z = max(exitPos.z, elevation);
  1081.                         }
  1082.                 }
  1083.         }
  1084.  
  1085.         if (dirtyPos && !IsRemoteControlledInternal() && m_transformViewOnExit)
  1086.         {
  1087.                 // set the position, but keep the orientation
  1088.                 passengerTM.SetTranslation(exitPos);
  1089.                 // move the entity( during serialize, don't change the postiin
  1090.                 if (!gEnv->pSystem->IsSerializingFile())
  1091.                         pPassengerEntity->SetWorldTM(passengerTM, ENTITY_XFORM_USER);
  1092.         }
  1093.  
  1094. #if ENABLE_VEHICLE_DEBUG
  1095.         if (VehicleCVars().v_debugdraw > 0)
  1096.         {
  1097.                 CPersistantDebug* pDB = CCryAction::GetCryAction()->GetPersistantDebug();
  1098.                 pDB->Begin("Seat", false);
  1099.                 pDB->AddDirection(passengerTM.GetTranslation() + Vec3(0, 0, 0.5f), 0.25f, passengerTM.GetColumn(1), ColorF(1, 1, 0, 1), 5.f);
  1100.         }
  1101. #endif
  1102.  
  1103.         // downgrade the vehicle update slot
  1104.         m_pVehicle->GetGameObject()->DisableUpdateSlot(m_pVehicle, IVehicle::eVUS_PassengerIn);
  1105.  
  1106.         // broadcast an event about the passenger exiting
  1107.         SVehicleEventParams eventParams;
  1108.         eventParams.iParam = m_seatId;
  1109.         eventParams.entityId = pActor->GetEntityId();
  1110.         m_pVehicle->BroadcastVehicleEvent(eVE_PassengerExit, eventParams);
  1111.  
  1112.         CHANGED_NETWORK_STATE(m_pVehicle, CVehicle::ASPECT_SEAT_PASSENGER);
  1113.  
  1114.         if (!gEnv->pSystem->IsSerializingFile()) //serialization will fix that automatically
  1115.         {
  1116.                 if (!pActor->IsDead())
  1117.                 {
  1118.                         if (IInventory* pInventory = pActor->GetInventory())
  1119.                         {
  1120.                                 IItem* pCurrentItem = gEnv->pGameFramework->GetIItemSystem()->GetItem(pInventory->GetCurrentItem());
  1121.                                 IWeapon* pWeapon = pCurrentItem ? pCurrentItem->GetIWeapon() : NULL;
  1122.                                 if (!pWeapon || !pWeapon->IsRippedOff())
  1123.                                         pActor->HolsterItem(false);
  1124.                         }
  1125.                 }
  1126.                 else
  1127.                 {
  1128.                         pActor->GetGameObject()->SetAspectProfile(eEA_Physics, eAP_Ragdoll);
  1129.                 }
  1130.  
  1131.                 if (pActor->IsPlayer())
  1132.                 {
  1133.                         if (m_transformViewOnExit)
  1134.                         {
  1135.                                 // align the look direction to the current vehicle view direction, to minimise the
  1136.                                 // snap when exiting
  1137.  
  1138.                                 IView* pView = gEnv->pGameFramework->GetIViewSystem()->GetActiveView();
  1139.  
  1140.                                 if (pView)
  1141.                                 {
  1142.                                         SViewParams params = *pView->GetCurrentParams();
  1143.  
  1144.                                         pActor->SetViewRotation(Quat::CreateRotationVDir(params.GetRotationLast().GetColumn1().GetNormalized()));
  1145.                                 }
  1146.                         }
  1147.                         else
  1148.                         {
  1149.                                 //Make sure we aren't left with any view roll
  1150.                                 IView* pView = gEnv->pGameFramework->GetIViewSystem()->GetActiveView();
  1151.  
  1152.                                 if (pView)
  1153.                                 {
  1154.                                         SViewParams params = *pView->GetCurrentParams();
  1155.                                         params.SaveLast();
  1156.                                         Ang3 currentAngles(params.GetRotationLast());
  1157.                                         if (fabs(currentAngles.y) > 0.01f)
  1158.                                         {
  1159.                                                 currentAngles.y = 0.f;
  1160.                                                 pActor->SetViewRotation(Quat(currentAngles));
  1161.                                         }
  1162.                                 }
  1163.                         }
  1164.  
  1165.                         pActor->GetEntity()->Hide(false);
  1166.                 }
  1167.         }
  1168.  
  1169.         m_transitionType = eVT_None;
  1170.  
  1171.         if (pActor->IsClient())
  1172.         {
  1173.                 StopSounds();
  1174.         }
  1175.  
  1176.         eventParams.entityId = pActor->GetEntityId();
  1177.         eventParams.iParam = m_seatId;
  1178.         m_pVehicle->BroadcastVehicleEvent(eVE_SeatFreed, eventParams);
  1179.  
  1180.         CCryAction::GetCryAction()->GetIGameplayRecorder()->Event(pActor->GetEntity(), GameplayEvent(eGE_LeftVehicle, 0, 0, (void*)(EXPAND_PTR)m_pVehicle->GetEntityId()));
  1181.  
  1182.         m_exitWorldPos.zero();
  1183.  
  1184.         return true;
  1185. }
  1186.  
  1187. //------------------------------------------------------------------------
  1188. void CVehicleSeat::OnSeatFreed(TVehicleSeatId seatId, EntityId passengerId)
  1189. {
  1190.         if (seatId == m_seatId || !m_passengerId || m_passengerId == passengerId)
  1191.                 return;
  1192.  
  1193.         // if remote seat freed by someone else, try to occupy it
  1194.         if (!gEnv->pSystem->IsSerializingFile())
  1195.         {
  1196.                 if (CVehicleSeat* pSeat = GetSeatUsedRemotely(false))
  1197.                 {
  1198.                         if (pSeat->GetSeatId() == seatId)
  1199.                         {
  1200.                                 pSeat->EnterRemotely(m_passengerId);
  1201.                         }
  1202.                 }
  1203.         }
  1204. }
  1205.  
  1206. //------------------------------------------------------------------------
  1207. void CVehicleSeat::GivesActorSeatFeatures(bool enabled, bool isRemote)
  1208. {
  1209.         IActor* pActor = m_pGameFramework->GetIActorSystem()->GetActor(m_passengerId);
  1210.         INetContext* pNetContext = m_pGameFramework->GetGameContext() ? m_pGameFramework->GetGameContext()->GetNetContext() : 0;
  1211.         const bool isActorEnslaved = ShouldEnslaveActorAnimations();
  1212.  
  1213.         if (enabled && !m_pVehicle->IsDestroyed() && (pActor && !pActor->IsDead() || gEnv->pSystem->IsSerializingFile())) // move this to PostSerialize (after alpha build..)
  1214.         {
  1215.                 IActionController* pActionController = m_pVehicle->GetAnimationComponent().GetActionController();
  1216.                 if (pActionController && isActorEnslaved)
  1217.                 {
  1218.                         if (m_seatFragmentIDs[eMannequinSeatAction_Idle] != TAG_ID_INVALID)
  1219.                         {
  1220.                                 m_pIdleAction = new TAction<SAnimationContext>(IVehicleAnimationComponent::ePriority_SeatDefault, m_seatFragmentIDs[eMannequinSeatAction_Idle], TAG_STATE_EMPTY);
  1221.                                 pActionController->Queue(*m_pIdleAction);
  1222.                         }
  1223.                 }
  1224.  
  1225.                 if (m_isDriver)
  1226.                 {
  1227.                         // give authority of the vehicle entity to whoever just sat down
  1228.                         if (gEnv->bServer && pActor->IsPlayer())
  1229.                         {
  1230.                                 CGameChannel* pGameChannel = GetGameChannel(m_passengerId);
  1231.  
  1232.                                 if (pGameChannel && pNetContext)
  1233.                                         pNetContext->DelegateAuthority(m_pVehicle->GetEntityId(), pGameChannel->GetNetChannel());
  1234.                         }
  1235.                 }
  1236.  
  1237.                 // enable the seat actions
  1238.                 for (TVehicleSeatActionVector::iterator ite = m_seatActions.begin(); ite != m_seatActions.end(); ++ite)
  1239.                 {
  1240.                         SSeatActionData& seatActionData = *ite;
  1241.  
  1242.                         if (seatActionData.isEnabled && (!isRemote || isRemote && seatActionData.isAvailableRemotely))
  1243.                                 seatActionData.pSeatAction->StartUsing(m_passengerId);
  1244.                 }
  1245.  
  1246.                 if (!isRemote && pActor->IsClient())
  1247.                 {
  1248.                         if (CAnimatedCharacter* pAnimChar = (CAnimatedCharacter*)(pActor->GetAnimatedCharacter()))
  1249.                         {
  1250.                                 pAnimChar->RegisterListener(this, "VehicleSeat");
  1251.                         }
  1252.  
  1253.                         bool isThirdPerson = true;
  1254.                         if (IVehicleView* pView = GetCurrentView())
  1255.                                 isThirdPerson = pView->IsThirdPerson();
  1256.  
  1257.                         if (IVehicleMovement* pMovement = m_pVehicle->GetMovement())
  1258.                         {
  1259.                                 SVehicleMovementEventParams params;
  1260.                                 params.fValue = isThirdPerson ? 0.f : 1.f;
  1261.                                 params.bValue = true;
  1262.                                 pMovement->OnEvent(IVehicleMovement::eVME_PlayerEnterLeaveSeat, params);
  1263.                         }
  1264.  
  1265.                         if (IVehicleClient* pVehicleClient = GetVehicleClient())
  1266.                                 pVehicleClient->OnEnterVehicleSeat(this);
  1267.                 }
  1268.  
  1269.                 // give authority of the seat serializer to whoever just sat down
  1270.                 if (gEnv->bServer && pActor->IsPlayer() && gEnv->pEntitySystem->GetEntity(m_serializerId))
  1271.                 {
  1272.                         CGameChannel* pGameChannel = GetGameChannel(m_passengerId);
  1273.  
  1274.                         if (pGameChannel && pNetContext)
  1275.                                 pNetContext->DelegateAuthority(m_serializerId, pGameChannel->GetNetChannel());
  1276.                 }
  1277.  
  1278.                 if (!isRemote)
  1279.                         UpdateHiddenState(true);
  1280.         }
  1281.         else if (!enabled)
  1282.         {
  1283.                 if (!isRemote)
  1284.                         UpdateHiddenState(false);
  1285.  
  1286.                 if (CVehicleSeat* pSeat = GetSeatUsedRemotely(true))
  1287.                         pSeat->ExitRemotely();
  1288.  
  1289.                 if (pActor)
  1290.                 {
  1291.                         if (!isRemote && pActor->IsClient())
  1292.                         {
  1293.                                 if (CAnimatedCharacter* pAnimChar = (CAnimatedCharacter*)(pActor->GetAnimatedCharacter()))
  1294.                                 {
  1295.                                         pAnimChar->UnregisterListener(this);
  1296.                                 }
  1297.  
  1298.                                 if (IVehicleMovement* pMovement = m_pVehicle->GetMovement())
  1299.                                 {
  1300.                                         SVehicleMovementEventParams params;
  1301.                                         params.fValue = 0.0f;
  1302.                                         params.bValue = false;
  1303.                                         pMovement->OnEvent(IVehicleMovement::eVME_PlayerEnterLeaveSeat, params);
  1304.                                 }
  1305.  
  1306.                                 if (IVehicleClient* pVehicleClient = GetVehicleClient())
  1307.                                         pVehicleClient->OnExitVehicleSeat(this);
  1308.  
  1309.                                 if ((VehicleCVars().v_playerTransitions == 0) || (m_transitionType == eVT_None))
  1310.                                 {
  1311.                                         if (GetCurrentViewId() != InvalidVehicleViewId)
  1312.                                                 SetView(InvalidVehicleViewId);
  1313.                                 }
  1314.  
  1315.                                 StopSounds();
  1316.                         }
  1317.  
  1318.                         if (m_isDriver && pNetContext && gEnv->bServer)
  1319.                                 pNetContext->DelegateAuthority(m_pVehicle->GetEntityId(), 0);
  1320.                 }
  1321.  
  1322.                 // give authority of the seat serializer to server
  1323.                 if (pNetContext && gEnv->bServer && gEnv->pEntitySystem->GetEntity(m_serializerId))
  1324.                         pNetContext->DelegateAuthority(m_serializerId, 0);
  1325.  
  1326.                 // disable the seat actions
  1327.                 for (TVehicleSeatActionVector::iterator ite = m_seatActions.begin(); ite != m_seatActions.end(); ++ite)
  1328.                 {
  1329.                         SSeatActionData& seatActionData = *ite;
  1330.  
  1331.                         if (seatActionData.isEnabled && (!isRemote || seatActionData.isAvailableRemotely))
  1332.                                 seatActionData.pSeatAction->StopUsing();
  1333.                 }
  1334.         }
  1335. }
  1336.  
  1337. //------------------------------------------------------------------------
  1338. EntityId CVehicleSeat::GetPassenger(bool remoteUser /*=false*/) const
  1339. {
  1340.         if (!remoteUser && m_transitionType == eVT_RemoteUsage)
  1341.                 return 0;
  1342.  
  1343.         return m_passengerId;
  1344. }
  1345.  
  1346. //------------------------------------------------------------------------
  1347. IActor* CVehicleSeat::GetPassengerActor(bool remoteUser /*=false*/) const
  1348. {
  1349.         EntityId id = GetPassenger(remoteUser);
  1350.  
  1351.         if (0 == id)
  1352.                 return NULL;
  1353.  
  1354.         return CCryAction::GetCryAction()->GetIActorSystem()->GetActor(id);
  1355. }
  1356.  
  1357. //------------------------------------------------------------------------
  1358. bool CVehicleSeat::IsPassengerClientActor() const
  1359. {
  1360.         if (m_passengerId)
  1361.         {
  1362.                 IActor* pActor = CCryAction::GetCryAction()->GetClientActor();
  1363.                 if (pActor && pActor->GetEntityId() == m_passengerId)
  1364.                         return true;
  1365.         }
  1366.  
  1367.         return false;
  1368. }
  1369.  
  1370. //------------------------------------------------------------------------
  1371. int CVehicleSeat::GetSeatActionId(IVehicleSeatAction* pAction) const
  1372. {
  1373.         int action = 0;
  1374.         for (TVehicleSeatActionVector::const_iterator ite = m_seatActions.begin(); ite != m_seatActions.end(); ++ite, ++action)
  1375.         {
  1376.                 const SSeatActionData& seatActionData = *ite;
  1377.                 if (seatActionData.pSeatAction == pAction)
  1378.                         return action;
  1379.         }
  1380.  
  1381.         return -1;
  1382. }
  1383.  
  1384. //------------------------------------------------------------------------
  1385. const IVehicleSeatAction* CVehicleSeat::GetSeatActionById(int id) const
  1386. {
  1387.         if (id >= 0)
  1388.         {
  1389.                 int action = 0;
  1390.                 for (TVehicleSeatActionVector::const_iterator ite = m_seatActions.begin(), iteEnd = m_seatActions.end(); ite != iteEnd; ++ite, ++action)
  1391.                 {
  1392.                         const SSeatActionData& seatActionData = *ite;
  1393.                         if (id == action)
  1394.                                 return seatActionData.pSeatAction;
  1395.                 }
  1396.         }
  1397.         return 0;
  1398. }
  1399.  
  1400. //------------------------------------------------------------------------
  1401. void CVehicleSeat::ChangedNetworkState(NetworkAspectType aspects)
  1402. {
  1403.         if (m_pSerializer && gEnv->pEntitySystem->GetEntity(m_serializerId))
  1404.         {
  1405.                 CHANGED_NETWORK_STATE(m_pSerializer, aspects);
  1406.         }
  1407. }
  1408.  
  1409. //------------------------------------------------------------------------
  1410. bool CVehicleSeat::IsFree(IActor* pInActor)
  1411. {
  1412.         if (IsLocked(pInActor))
  1413.                 return false;
  1414.  
  1415.         if (!m_passengerId)
  1416.                 return true;
  1417.  
  1418.         IActor* pCurrentActor = CCryAction::GetCryAction()->GetIActorSystem()->GetActor(m_passengerId);
  1419.         if (!pCurrentActor)
  1420.                 return true;
  1421.  
  1422.         if (m_transitionType == eVT_RemoteUsage)
  1423.                 return true;
  1424.  
  1425.         return pCurrentActor->IsDead();
  1426. }
  1427.  
  1428. //------------------------------------------------------------------------
  1429. void CVehicleSeat::OnAction(const TVehicleActionId actionId, int activationMode, float value)
  1430. {
  1431.         IActorSystem* pActorSystem = gEnv->pGameFramework->GetIActorSystem();
  1432.         CRY_ASSERT(pActorSystem);
  1433.  
  1434.         IActor* pActor = pActorSystem->GetActor(m_passengerId);
  1435.  
  1436.         if (!pActor)
  1437.         {
  1438.                 return;
  1439.         }
  1440.  
  1441.         if (pActor->IsDead())
  1442.                 return;
  1443.  
  1444.         if (!m_pVehicle->IsDestroyed())
  1445.         {
  1446.                 for (TVehicleSeatActionVector::iterator ite = m_seatActions.begin(); ite != m_seatActions.end(); ++ite)
  1447.                 {
  1448.                         SSeatActionData& seatActionData = *ite;
  1449.  
  1450.                         // skip disabled actions
  1451.                         if (!seatActionData.isEnabled)
  1452.                                 continue;
  1453.  
  1454.                         if (m_transitionType == eVT_None ||
  1455.                             (m_transitionType == eVT_RemoteUsage && seatActionData.isAvailableRemotely) ||
  1456.                             (m_transitionType == eVT_Entering && pActor->IsClient()))
  1457.                         {
  1458.                                 seatActionData.pSeatAction->OnAction(actionId, activationMode, value);
  1459.                         }
  1460.                 }
  1461.  
  1462.                 if (CVehicleSeat* pRemoteSeat = GetSeatUsedRemotely(true))
  1463.                         pRemoteSeat->OnAction(actionId, activationMode, value);
  1464.         }
  1465.  
  1466.         if (actionId == eVAI_ChangeView)
  1467.                 SetView(GetNextAvailableViewId());
  1468.  
  1469.         if (IVehicleView* pView = GetCurrentView())
  1470.                 pView->OnAction(actionId, activationMode, value);
  1471. }
  1472.  
  1473. //------------------------------------------------------------------------
  1474. void CVehicleSeat::Update(float deltaTime)
  1475. {
  1476.         FUNCTION_PROFILER(GetISystem(), PROFILE_ACTION);
  1477.  
  1478.         IActor* pActor = GetPassengerActor();
  1479.         if (m_passengerId && pActor && pActor->GetEntity())
  1480.         {
  1481.                 // update passenger TM
  1482.                 if (pActor)
  1483.                 {
  1484.                         if (m_transitionType == eVT_Entering && pActor->IsPlayer() && (VehicleCVars().v_playerTransitions == 0))
  1485.                         {
  1486.                                 m_transitionType = eVT_None;
  1487.                         }
  1488.  
  1489.                         if (m_transitionType == eVT_None || m_transitionType == eVT_Dying)
  1490.                         {
  1491.                                 if (m_updatePassengerTM)
  1492.                                 {
  1493.                                         UpdatePassengerLocalTM(pActor);
  1494.                                 }
  1495.  
  1496. #if ENABLE_VEHICLE_DEBUG
  1497.                                 if (m_pSitHelper && VehicleCVars().v_draw_passengers == 1)
  1498.                                 {
  1499.                                         Matrix34 tm;
  1500.                                         m_pSitHelper->GetWorldTM(tm);
  1501.                                         VehicleUtils::DrawTM(tm, "VehicleSeat::Update", true);
  1502.                                 }
  1503. #endif
  1504.  
  1505.                                 if (pActor->IsClient())
  1506.                                 {
  1507.                                         UpdateRemote(pActor, deltaTime);
  1508.                                 }
  1509.  
  1510.                                 if (pActor && (m_transitionType == eVT_Dying) && (!pActor->IsPlayer()))
  1511.                                 {
  1512.                                         if (ICharacterInstance* pCharacter = pActor->GetEntity()->GetCharacter(0))
  1513.                                         {
  1514.                                                 if (ISkeletonPose* pSkeli = pCharacter->GetISkeletonPose())
  1515.                                                 {
  1516.                                                         if (IPhysicalEntity* pPE = pSkeli->GetCharacterPhysics())
  1517.                                                         {
  1518.                                                                 pe_params_part ppp;
  1519.                                                                 ppp.flagsAND = ~(geom_colltype_explosion | geom_colltype_ray | geom_colltype_foliage_proxy);
  1520.                                                                 pPE->SetParams(&ppp);
  1521.                                                         }
  1522.                                                 }
  1523.                                         }
  1524.                                 }
  1525.                         }
  1526.                         else if (m_transitionType == eVT_RemoteUsage)
  1527.                         {
  1528.                                 for (TVehicleSeatActionVector::iterator ite = m_seatActions.begin(); ite != m_seatActions.end(); ++ite)
  1529.                                 {
  1530.                                         SSeatActionData& seatActionData = *ite;
  1531.  
  1532.                                         if (seatActionData.isAvailableRemotely && seatActionData.isEnabled)
  1533.                                                 seatActionData.pSeatAction->Update(deltaTime);
  1534.                                 }
  1535.                         }
  1536.                         else if (m_transitionType == eVT_ExitingWarped)
  1537.                         {
  1538.                                 Vec3 warpToPos;
  1539.                                 AABB worldBounds;
  1540.  
  1541.                                 pActor->GetEntity()->GetWorldBounds(worldBounds);
  1542.  
  1543.                                 if (!gEnv->pRenderer->GetCamera().IsAABBVisible_F(worldBounds))
  1544.                                 {
  1545.                                         if (IAIObject* pAIObject = pActor->GetEntity()->GetAI())
  1546.                                         {
  1547.                                                 if (IAIPathAgent* aiactor = pAIObject->CastToIAIActor())
  1548.                                                         if (aiactor->GetTeleportPosition(m_adjustedExitPos))
  1549.                                                         {
  1550.                                                                 Exit(false);
  1551.                                                                 StandUp();
  1552.                                                         }
  1553.                                         }
  1554.                                 }
  1555.                         }
  1556.  
  1557.                         if (m_queuedTransition == eVT_Exiting)
  1558.                         {
  1559.                                 if (!QueueTransition())
  1560.                                         Exit(true, false);
  1561.                         }
  1562.  
  1563.                         UpdateSounds(deltaTime);
  1564.                 }
  1565.         }
  1566.         else
  1567.         {
  1568.                 for (TVehicleSeatActionVector::iterator ite = m_seatActions.begin(); ite != m_seatActions.end(); ++ite)
  1569.                 {
  1570.                         SSeatActionData& seatActionData = *ite;
  1571.  
  1572.                         if (!seatActionData.isEnabled || !seatActionData.pSeatAction)
  1573.                                 continue;
  1574.  
  1575.                         if (CVehicleSeatActionWeapons* pActionWeapons = CAST_VEHICLEOBJECT(CVehicleSeatActionWeapons, seatActionData.pSeatAction))
  1576.                         {
  1577.                                 seatActionData.pSeatAction->Update(deltaTime);
  1578.                         }
  1579.                 }
  1580.         }
  1581. }
  1582.  
  1583. void CVehicleSeat::UpdateRemote(IActor* pActor, float deltaTime)
  1584. {
  1585.         CVehicleSeat* pSeat = GetSeatUsedRemotely(true);
  1586.         if (!pSeat)
  1587.                 return;
  1588.  
  1589.         if (pSeat->IsGunner() && VehicleCVars().v_driverControlledMountedGuns)
  1590.         {
  1591.                 // merge this with vehicle weapon raycast (after alpha)
  1592.                 CVehicleSeatActionRotateTurret* pTurretAction = NULL;
  1593.  
  1594.                 TVehicleSeatActionVector& seatActions = pSeat->GetSeatActions();
  1595.                 for (TVehicleSeatActionVector::const_iterator it = seatActions.begin(); it != seatActions.end(); ++it)
  1596.                 {
  1597.                         if (!it->isAvailableRemotely)
  1598.                                 continue;
  1599.  
  1600.                         if (pTurretAction = CAST_VEHICLEOBJECT(CVehicleSeatActionRotateTurret, it->pSeatAction))
  1601.                                 break;
  1602.                 }
  1603.  
  1604.                 IMovementController* pMC = (pActor != NULL) ? pActor->GetMovementController() : NULL;
  1605.                 if (pMC && pTurretAction)
  1606.                 {
  1607.                         IVehicleView* pView = GetCurrentView();
  1608.                         if (pView && pView->IsAvailableRemotely() && pView->IsThirdPerson())
  1609.                         {
  1610.                                 // remote thirdperson view uses AimPart as usual
  1611.                                 pTurretAction->SetAimGoal(Vec3Constants<float>::fVec3_Zero);
  1612.                         }
  1613.                         else
  1614.                         {
  1615.                                 // when using fp view, set AimGoal on Turret action
  1616.                                 SMovementState info;
  1617.                                 pMC->GetMovementState(info);
  1618.  
  1619.                                 ray_hit rayhit;
  1620.                                 static IPhysicalEntity* pSkipEnts[10];
  1621.                                 pSkipEnts[0] = m_pVehicle->GetEntity()->GetPhysics();
  1622.                                 int nskip = 0;
  1623.  
  1624.                                 for (int i = 0, count = m_pVehicle->GetEntity()->GetChildCount(); i < count && nskip < 9; ++i)
  1625.                                 {
  1626.                                         IEntity* pChild = m_pVehicle->GetEntity()->GetChild(i);
  1627.                                         IPhysicalEntity* pPhysics = pChild->GetPhysics();
  1628.                                         if (pPhysics)
  1629.                                         {
  1630.                                                 // todo: shorter way to handle this?
  1631.                                                 if (pPhysics->GetType() == PE_LIVING)
  1632.                                                         if (ICharacterInstance* pCharacter = pChild->GetCharacter(0))
  1633.                                                                 if (IPhysicalEntity* pCharPhys = pCharacter->GetISkeletonPose()->GetCharacterPhysics())
  1634.                                                                         pPhysics = pCharPhys;
  1635.  
  1636.                                                 pSkipEnts[++nskip] = pPhysics;
  1637.                                         }
  1638.                                 }
  1639.  
  1640.                                 int hits = gEnv->pPhysicalWorld->RayWorldIntersection(info.weaponPosition, info.aimDirection * 200.f, ent_all,
  1641.                                                                                       rwi_stop_at_pierceable | rwi_colltype_any, &rayhit, 1, pSkipEnts, nskip + 1);
  1642.  
  1643.                                 if (hits)
  1644.                                         pTurretAction->SetAimGoal(rayhit.pt);
  1645.                                 else
  1646.                                         pTurretAction->SetAimGoal(info.weaponPosition + 1000.f * info.aimDirection);
  1647.                         }
  1648.                 }
  1649.         }
  1650. }
  1651.  
  1652. //------------------------------------------------------------------------
  1653. void CVehicleSeat::UpdatePassengerLocalTM(IActor* pActor)
  1654. {
  1655.         if (m_pSitHelper && (VehicleCVars().v_set_passenger_tm != 0) && !IsRemoteControlledInternal())
  1656.         {
  1657.                 // todo: optimize this to only update after invalidation
  1658.  
  1659.                 Matrix34 tm;
  1660.  
  1661.                 m_pSitHelper->GetVehicleTM(tm);
  1662.                 pActor->GetEntity()->SetLocalTM(tm);
  1663.  
  1664.         }
  1665. }
  1666.  
  1667. //------------------------------------------------------------------------
  1668. IVehicleView* CVehicleSeat::GetView(TVehicleViewId viewId) const
  1669. {
  1670.         if (viewId < FirstVehicleViewId || viewId > m_views.size())
  1671.                 return NULL;
  1672.  
  1673.         IVehicleView* pView = m_views[viewId - 1];
  1674.  
  1675.         if (CVehicleSeat* pSeat = GetSeatUsedRemotely(true))
  1676.         {
  1677.                 if (IVehicleView* pRemoteView = pSeat->GetView(viewId))
  1678.                 {
  1679.                         if (pRemoteView->IsAvailableRemotely() && pRemoteView->IsThirdPerson() == pView->IsThirdPerson())
  1680.                                 pView = pRemoteView;
  1681.                 }
  1682.         }
  1683.  
  1684.         return pView;
  1685. }
  1686.  
  1687. //------------------------------------------------------------------------
  1688. bool CVehicleSeat::SetView(TVehicleViewId viewId)
  1689. {
  1690.         if (viewId < InvalidVehicleViewId || viewId > m_views.size() || viewId == m_currentView)
  1691.         {
  1692.                 return false;
  1693.         }
  1694.  
  1695.         if (viewId == InvalidVehicleViewId)
  1696.         {
  1697.                 if (IVehicleView* pOldView = GetCurrentView())
  1698.                         pOldView->OnStopUsing();
  1699.         }
  1700.         else
  1701.         {
  1702.                 IActor* pActor = gEnv->pGameFramework->GetClientActor();
  1703.                 if (!pActor || pActor->GetEntityId() != m_passengerId)
  1704.                 {
  1705.                         return false;
  1706.                 }
  1707.  
  1708.                 IVehicleView* pNewView = GetView(viewId);
  1709.                 if (!pNewView || !pNewView->IsEnabled())
  1710.                 {
  1711.                         return false;
  1712.                 }
  1713.  
  1714.                 if (IVehicleView* pOldView = GetCurrentView())
  1715.                         pOldView->OnStopUsing();
  1716.  
  1717.                 pNewView->OnStartUsing(m_passengerId);
  1718.  
  1719.                 const bool bIsThirdPerson = pNewView->IsThirdPerson();
  1720.  
  1721.                 SVehicleEventParams params;
  1722.                 params.bParam = bIsThirdPerson;
  1723.                 m_pVehicle->BroadcastVehicleEvent(eVE_ViewChanged, params);
  1724.  
  1725.                 if (IVehicleMovement* pMovement = m_pVehicle->GetMovement())
  1726.                 {
  1727.                         SVehicleMovementEventParams vehicle_Movement_Params;
  1728.                         vehicle_Movement_Params.fValue = bIsThirdPerson ? 0.0f : 1.0f;
  1729.                         pMovement->OnEvent(IVehicleMovement::eVME_PlayerSwitchView, vehicle_Movement_Params);
  1730.                 }
  1731.         }
  1732.  
  1733.         m_currentView = viewId;
  1734.  
  1735.         return true;
  1736. }
  1737.  
  1738. //------------------------------------------------------------------------
  1739. TVehicleViewId CVehicleSeat::GetNextViewId(bool bExcludeDebug, bool bExcludeDisabled) const
  1740. {
  1741.         TVehicleViewId nextId = m_currentView + 1;
  1742.         for (int i = 0; i < m_views.size(); ++i)
  1743.         {
  1744.                 if (nextId > m_views.size())
  1745.                 {
  1746.                         nextId = FirstVehicleViewId;
  1747.                 }
  1748.  
  1749.                 IVehicleView* pNextView = GetView(nextId);
  1750.                 if ((bExcludeDebug && pNextView->IsDebugView()) || (bExcludeDisabled && !pNextView->IsEnabled()))
  1751.                 {
  1752.                         nextId++;
  1753.                 }
  1754.                 else
  1755.                 {
  1756.                         // found good view
  1757.                         return nextId;
  1758.                 }
  1759.         }
  1760.  
  1761.         // looped without finding an adequate view. The current could be the only one or also invalid, in either case, return invalid.
  1762.         return InvalidVehicleViewId;
  1763. }
  1764.  
  1765. //------------------------------------------------------------------------
  1766. void CVehicleSeat::UpdateView(SViewParams& viewParams)
  1767. {
  1768.         CRY_ASSERT(m_passengerId);
  1769.  
  1770.         if ((m_transitionType == eVT_None) || (VehicleCVars().v_playerTransitions == 1))
  1771.         {
  1772.                 if (IVehicleView* pView = GetCurrentView())
  1773.                         pView->UpdateView(viewParams, m_passengerId);
  1774.         }
  1775.         else
  1776.         {
  1777.                 if (IActor* pActor = m_pGameFramework->GetIActorSystem()->GetActor(m_passengerId))
  1778.                 {
  1779.                         IEntity* pEntity = pActor->GetEntity();
  1780.                         CRY_ASSERT(pEntity);
  1781.  
  1782.                         if (ICharacterInstance* pCharInstance = pEntity->GetCharacter(0))
  1783.                         {
  1784.                                 IDefaultSkeleton& rIDefaultSkeleton = pCharInstance->GetIDefaultSkeleton();
  1785.                                 ISkeletonPose* pSkeletonPose = pCharInstance->GetISkeletonPose();
  1786.                                 CRY_ASSERT(pSkeletonPose);
  1787.  
  1788.                                 int16 headId = rIDefaultSkeleton.GetJointIDByName("Bip01 Head");
  1789.                                 if (headId > -1)
  1790.                                 {
  1791.                                         Matrix34 worldTM = pEntity->GetSlotWorldTM(0) * Matrix34(pSkeletonPose->GetAbsJointByID(headId));
  1792.                                         worldTM.OrthonormalizeFast();
  1793.  
  1794.                                         viewParams.position = worldTM.GetTranslation();
  1795.                                         viewParams.rotation = Quat(Matrix33(worldTM)).GetNormalized() * Quat::CreateRotationY(gf_PI * 0.5f);
  1796.  
  1797.                                         if (ICVar* pVar = gEnv->pConsole->GetCVar("cl_fov"))
  1798.                                                 viewParams.fov = DEG2RAD(pVar->GetFVal());
  1799.                                         else
  1800.                                                 viewParams.fov = 0.0f;
  1801.  
  1802.                                         viewParams.nearplane = 0.0f;
  1803.                                 }
  1804.                         }
  1805.                 }
  1806.         }
  1807.  
  1808.         if (!m_isPlayerViewBlending || m_skipViewBlending)
  1809.         {
  1810.                 viewParams.SetViewID(2, false);
  1811.                 m_skipViewBlending = false;
  1812.         }
  1813. }
  1814.  
  1815. //------------------------------------------------------------------------
  1816. void CVehicleSeat::UpdateSounds(float deltaTime)
  1817. {
  1818.         if (!(m_transitionType != eVT_RemoteUsage && IsPassengerClientActor()))
  1819.                 return;
  1820.  
  1821.         SSeatSoundParams& params = GetSoundParams();
  1822.         const char* moodName = params.moodName.c_str();
  1823.  
  1824.         float mood = params.mood;
  1825.  
  1826.         if (IVehicleView* pView = GetCurrentView())
  1827.         {
  1828.                 if (pView->IsThirdPerson())
  1829.                 {
  1830.                         mood = 0.f;
  1831.                 }
  1832.         }
  1833.  
  1834.         REINST("update state for being in-car");
  1835. }
  1836.  
  1837. //------------------------------------------------------------------------
  1838. void CVehicleSeat::StopSounds()
  1839. {
  1840.         REINST("is this needed?");
  1841.         GetSoundParams().moodCurr = 0.f;
  1842. }
  1843.  
  1844. //------------------------------------------------------------------------
  1845. EntityId CVehicleSeat::NetGetPassengerId() const
  1846. {
  1847.         return m_passengerId;
  1848. }
  1849.  
  1850. //------------------------------------------------------------------------
  1851. void CVehicleSeat::NetSetPassengerId(EntityId passengerId)
  1852. {
  1853.         if (passengerId != m_passengerId)
  1854.         {
  1855.                 //CryLog("%s::NetSetPassenger: <%s> %i -> %i", m_pVehicle->GetEntity()->GetClass()->GetName(), m_name.c_str(), m_passengerId, passengerId);
  1856.  
  1857.                 IActorSystem* pActorSystem = CCryAction::GetCryAction()->GetIActorSystem();
  1858.                 CRY_ASSERT(pActorSystem);
  1859.  
  1860.                 IActor* pActor = pActorSystem->GetActor(passengerId ? passengerId : m_passengerId);
  1861.                 if (!pActor)
  1862.                         return;
  1863.  
  1864.                 // resolve the previous seat situation if any,
  1865.                 // because passengers need to leave their current seat before entering the new one
  1866.                 CVehicleSeat* pPrevSeat = (CVehicleSeat*)m_pVehicle->GetSeatForPassenger(passengerId);
  1867.                 if (pPrevSeat)
  1868.                 {
  1869.                         if (pPrevSeat->m_transitionType == eVT_RemoteUsage)
  1870.                                 pPrevSeat->ExitRemotely();
  1871.                         else
  1872.                         {
  1873.                                 pActor->GetEntity()->GetCharacter(0)->GetISkeletonAnim()->StopAnimationsAllLayers();
  1874.  
  1875.                                 pPrevSeat->GivesActorSeatFeatures(false);
  1876.  
  1877.                                 pPrevSeat->m_passengerId = 0;
  1878.  
  1879.                                 SVehicleEventParams ep;
  1880.                                 ep.entityId = passengerId;
  1881.                                 ep.iParam = m_seatId;
  1882.                                 m_pVehicle->BroadcastVehicleEvent(eVE_SeatFreed, ep);
  1883.                         }
  1884.                 }
  1885.  
  1886.                 EntityId exitId = m_passengerId;
  1887.                 EntityId enterId = (!pActor->IsDead() && !m_pVehicle->IsDestroyed() && passengerId) ? passengerId : 0;
  1888.  
  1889.                 if (exitId)
  1890.                 {
  1891.                         if (m_prevTransitionType == eVT_RemoteUsage)
  1892.                         {
  1893.                                 ExitRemotely();
  1894.                         }
  1895.                         else
  1896.                         {
  1897.                                 CryLog("[VEHICLE] [%s] SERIALISING EXIT: Vehicle[%u] Passenger[%u]", gEnv->bServer ? "SERVER" : "CLIENT", m_pVehicle->GetEntityId(), m_passengerId);
  1898.  
  1899.                                 Exit(true, true);
  1900.                         }
  1901.  
  1902.                         m_prevTransitionType = eVT_None;
  1903.                 }
  1904.  
  1905.                 if (enterId)
  1906.                 {
  1907.                         if (pActor->GetLinkedEntity() != m_pVehicle->GetEntity())
  1908.                         {
  1909.                                 Enter(enterId, (VehicleCVars().v_playerTransitions == 1));
  1910.                         }
  1911.                         else
  1912.                         {
  1913.                                 CryLog("[VEHICLE] [%s] SERIALISING ENTR: Vehicle[%d] Passenger[%d]", gEnv->bServer ? "SERVER" : "CLIENT", m_pVehicle->GetEntityId(), passengerId);
  1914.  
  1915.                                 m_passengerId = passengerId;
  1916.                                 if (m_transitionType != eVT_RemoteUsage)
  1917.                                 {
  1918.                                         if (!IsRemoteControlledInternal())
  1919.                                         {
  1920.                                                 SitDown();
  1921.                                         }
  1922.                                 }
  1923.                                 else
  1924.                                 {
  1925.                                         EnterRemotely(enterId);
  1926.                                 }
  1927.                         }
  1928.                         m_prevTransitionType = m_transitionType;
  1929.                 }
  1930.  
  1931.                 CHANGED_NETWORK_STATE(m_pVehicle, CVehicle::ASPECT_SEAT_PASSENGER);
  1932.         }
  1933. }
  1934.  
  1935. //------------------------------------------------------------------------
  1936. void CVehicleSeat::Serialize(TSerialize ser, EEntityAspects aspects)
  1937. {
  1938.         if (ser.GetSerializationTarget() != eST_Network)
  1939.         {
  1940.                 if (ser.IsWriting())
  1941.                 {
  1942.                         ser.Value("passengerId", m_passengerId, 'eid');
  1943.  
  1944.                         IActor* pActor = m_pGameFramework->GetIActorSystem()->GetActor(m_passengerId);
  1945.                         bool forceEnter = pActor && pActor->GetEntity();
  1946.  
  1947.                         ser.Value("forceEnter", forceEnter);
  1948.                         ser.EnumValue("isLocked", m_lockStatus, eVSLS_Unlocked, eVSLS_Locked);
  1949.                         ser.Value("transition", m_transitionType);
  1950.                         ser.Value("queueTransition", m_queuedTransition);
  1951.                 }
  1952.                 else if (ser.IsReading())
  1953.                 {
  1954.                         EntityId passengerId;
  1955.                         int transitionType = 0, queueTransitionType = 0;
  1956.  
  1957.                         bool forceEnter = false;
  1958.  
  1959.                         ser.Value("passengerId", passengerId, 'eid');
  1960.                         ser.Value("forceEnter", forceEnter);
  1961.  
  1962.                         ser.EnumValue("isLocked", m_lockStatus, eVSLS_Unlocked, eVSLS_Locked);
  1963.                         ser.Value("transition", transitionType);
  1964.                         ser.Value("queueTransition", queueTransitionType);
  1965.  
  1966.                         IActor* pActor = NULL;
  1967.                         if (passengerId)
  1968.                                 pActor = m_pGameFramework->GetIActorSystem()->GetActor(passengerId);
  1969.  
  1970.                         IActor* pActorBefore = NULL;
  1971.                         if (m_passengerId)
  1972.                         {
  1973.                                 pActorBefore = m_pGameFramework->GetIActorSystem()->GetActor(m_passengerId);
  1974.                                 if ((pActorBefore != NULL) && pActorBefore->IsDead())
  1975.                                         Exit(false, true);
  1976.                         }
  1977.  
  1978.                         // remove current passenger if necessary
  1979.                         if (m_passengerId && (!pActor || passengerId != m_passengerId))
  1980.                                 Exit(false, true);
  1981.  
  1982.                         if (pActor)
  1983.                         {
  1984.                                 bool remote = (transitionType == eVT_RemoteUsage);
  1985.  
  1986.                                 if (passengerId != GetPassenger(remote))
  1987.                                 {
  1988.                                         // exit previous seat if any
  1989.                                         if (!remote)
  1990.                                         {
  1991.                                                 if (IVehicle* pPrevVehicle = pActor->GetLinkedVehicle())
  1992.                                                 {
  1993.                                                         if (IVehicleSeat* pPrevSeat = pPrevVehicle->GetSeatForPassenger(pActor->GetEntityId()))
  1994.                                                                 pPrevSeat->Exit(false, true);
  1995.                                                 }
  1996.                                         }
  1997.  
  1998.                                         m_postEnterId = passengerId;
  1999.  
  2000.                                         /*if (remote)
  2001.                                            EnterRemotely(passengerId);
  2002.                                            else
  2003.                                            Enter(passengerId, false);
  2004.                                          */
  2005.                                 }
  2006.  
  2007.                                 if (forceEnter)
  2008.                                 {
  2009.                                         m_postEnterId = passengerId;
  2010.                                 }
  2011.                         }
  2012.  
  2013.                         m_transitionType = transitionType;
  2014.                         m_queuedTransition = queueTransitionType;
  2015.                         m_passengerId = passengerId;
  2016.                         m_pVehicle->GetGameObject()->EnableUpdateSlot(m_pVehicle, IVehicle::eVUS_PassengerIn);
  2017.                 }
  2018.  
  2019.                 TVehicleViewId view = m_currentView;
  2020.                 ser.Value("currentViewId", view);
  2021.  
  2022.                 if (ser.IsReading() && view != m_currentView && m_transitionType != eVT_RemoteUsage)
  2023.                 {
  2024.                         m_postViewId = view;
  2025.                 }
  2026.  
  2027.                 if (IVehicleView* pView = GetView(view))
  2028.                         pView->Serialize(ser, aspects);
  2029.  
  2030.                 int i = 0;
  2031.                 char pSeatActionString[32];
  2032.  
  2033.                 for (TVehicleSeatActionVector::iterator ite = m_seatActions.begin(); ite != m_seatActions.end(); ++ite)
  2034.                 {
  2035.                         cry_sprintf(pSeatActionString, "seatAction_%d", ++i);
  2036.  
  2037.                         ser.BeginGroup(pSeatActionString);
  2038.                         ite->Serialize(ser, aspects);
  2039.                         ser.EndGroup();
  2040.                 }
  2041.         }
  2042.         // network
  2043.         else
  2044.         {
  2045.                 if (aspects & CVehicle::ASPECT_SEAT_PASSENGER)
  2046.                 {
  2047.                         NET_PROFILE_SCOPE("VehicleSeat", ser.IsReading());
  2048.                         bool remotelyUsed = m_transitionType == eVT_RemoteUsage;
  2049.                         ser.Value("remotelyUsed", remotelyUsed, 'bool');
  2050.                         if (ser.IsReading() && remotelyUsed)
  2051.                                 m_transitionType = eVT_RemoteUsage;
  2052.  
  2053.                         ser.Value("passengerId", this, &CVehicleSeat::NetGetPassengerId, &CVehicleSeat::NetSetPassengerId, 'eid');
  2054.                 }
  2055.         }
  2056. }
  2057.  
  2058. //------------------------------------------------------------------------
  2059. void CVehicleSeat::PostSerialize()
  2060. {
  2061.         IActor* pActor = m_passengerId ? CCryAction::GetCryAction()->GetIActorSystem()->GetActor(m_passengerId) : 0;
  2062.         bool remote = (m_transitionType == eVT_RemoteUsage);
  2063.  
  2064.         if (pActor)
  2065.         {
  2066.                 if (m_postEnterId)
  2067.                 {
  2068.                         if (m_transitionType != eVT_Exiting)
  2069.                         {
  2070.                                 if (remote)
  2071.                                         EnterRemotely(m_passengerId);
  2072.                                 else if (pActor->GetEntity() && pActor->GetEntity()->GetAI())
  2073.                                 {
  2074.                                         bool needUpdateTM = false;
  2075.                                         if (m_isRagdollingOnDeath == false)
  2076.                                         {
  2077.                                                 if (pActor->GetGameObject()->GetAspectProfile(eEA_Physics) != eAP_Alive)
  2078.                                                 {
  2079.                                                         pActor->GetGameObject()->SetAspectProfile(eEA_Physics, eAP_Alive);
  2080.                                                         needUpdateTM = true;
  2081.                                                 }
  2082.                                         }
  2083.                                         Enter(m_passengerId, false);
  2084.                                         if (needUpdateTM)
  2085.                                                 UpdatePassengerLocalTM(pActor);
  2086.  
  2087.                                         if (pActor->IsDead())
  2088.                                                 OnPassengerDeath();
  2089.                                 }
  2090.                                 else
  2091.                                 {
  2092.                                         pActor->HolsterItem(true);
  2093.                                         pActor->MountedGunControllerEnabled(false);
  2094.  
  2095.                                         pActor->GetGameObject()->SetAspectProfile(eEA_Physics, eAP_Alive);
  2096.                                         Enter(m_passengerId, true);
  2097.                                 }
  2098.                         }
  2099.  
  2100.                         m_postEnterId = 0;
  2101.                 }
  2102.  
  2103.                 if (!remote)
  2104.                 {
  2105.                         pActor->HolsterItem(true);
  2106.  
  2107.                         if (m_postViewId)
  2108.                         {
  2109.                                 SetView(m_postViewId);
  2110.                                 m_postViewId = 0;
  2111.                         }
  2112.                 }
  2113.  
  2114.                 if (pActor->IsClient())
  2115.                 {
  2116.                         // don't interpolate view in this case
  2117.                         IVehicleView* pView = GetView(m_currentView);
  2118.                         if (pView)
  2119.                         {
  2120.                                 pView->ResetPosition();
  2121.                         }
  2122.                         m_skipViewBlending = true;
  2123.                 }
  2124.         }
  2125.  
  2126.         if (m_transitionType == eVT_Exiting)
  2127.                 StandUp();
  2128.  
  2129.         for (TVehicleSeatActionVector::iterator ite = m_seatActions.begin(); ite != m_seatActions.end(); ++ite)
  2130.         {
  2131.                 ite->pSeatAction->PostSerialize();
  2132.         }
  2133. }
  2134.  
  2135. //------------------------------------------------------------------------
  2136. CVehicleSeatSerializer* CVehicleSeat::GetSerializer()
  2137. {
  2138.         return m_pSerializer;
  2139. }
  2140.  
  2141. //------------------------------------------------------------------------
  2142. void CVehicleSeat::SetSerializer(CVehicleSeatSerializer* pSerializer)
  2143. {
  2144.         if (m_serializerId)
  2145.                 return;
  2146.  
  2147.         m_pSerializer = pSerializer;
  2148.         m_serializerId = m_pSerializer->GetEntityId();
  2149. }
  2150.  
  2151. //------------------------------------------------------------------------
  2152. float CVehicleSeat::ProcessPassengerDamage(float actorHealth, float damage, int hitTypeId, bool explosion)
  2153. {
  2154.         bool fire = (hitTypeId == CVehicle::s_fireHitTypeId);
  2155.         bool punish = (hitTypeId == CVehicle::s_punishHitTypeId);
  2156.  
  2157.         if (!punish && m_isPassengerShielded && !m_pVehicle->IsDestroyed())
  2158.         {
  2159.                 if (explosion || fire)
  2160.                         return 0.0f;
  2161.         }
  2162.  
  2163.         // todo: damage should not depend on sound parameters...
  2164.         if (fire)
  2165.                 return damage * m_soundParams.inout;
  2166.  
  2167.         return damage;
  2168. }
  2169.  
  2170. //------------------------------------------------------------------------
  2171. void CVehicleSeat::OnPassengerDeath()
  2172. {
  2173.         IActorSystem* pActorSystem = CCryAction::GetCryAction()->GetIActorSystem();
  2174.         CRY_ASSERT(pActorSystem);
  2175.  
  2176.         IActor* pActor = pActorSystem->GetActor(m_passengerId);
  2177.         if (!pActor)
  2178.                 return;
  2179.  
  2180.         if (m_transitionType == eVT_RemoteUsage)
  2181.         {
  2182.                 CRY_ASSERT(0 && "OnPassengerDeath called on remotely used seat");
  2183.                 return;
  2184.         }
  2185.  
  2186.         if (m_pSeatGroup)
  2187.                 m_pSeatGroup->OnPassengerExit(this, m_passengerId);
  2188.  
  2189.         if (m_isRagdollingOnDeath || m_transitionType == eVT_Entering || m_transitionType == eVT_Exiting ||
  2190.             VehicleCVars().v_ragdollPassengers == 1 || m_pVehicle->IsDestroyed() || pActor->IsPlayer())
  2191.         {
  2192.                 UnlinkPassenger(true);
  2193.  
  2194.                 if (pActor->IsPlayer() && m_pEnterHelper)
  2195.                 {
  2196.                         Matrix34 tm;
  2197.                         m_pEnterHelper->GetWorldTM(tm);
  2198.                         pActor->GetEntity()->SetWorldTM(tm);
  2199.                 }
  2200.  
  2201. #if ENABLE_VEHICLE_DEBUG
  2202.                 if (VehicleCVars().v_debugdraw)
  2203.                         CryLog("unlinked %s", pActor->GetEntity()->GetName());
  2204. #endif
  2205.         }
  2206.         else
  2207.         {
  2208.                 m_transitionType = eVT_Dying;
  2209.                 GivesActorSeatFeatures(false);
  2210.  
  2211. #if ENABLE_VEHICLE_DEBUG
  2212.                 if (VehicleCVars().v_debugdraw)
  2213.                         CryLog("%s: setting transition type eVT_Dying", pActor->GetEntity()->GetName());
  2214. #endif
  2215.         }
  2216.  
  2217.         // hide non-players when died from vehicle explosion
  2218.         if (!pActor->IsPlayer() && (m_pVehicle->IsDestroyed() || m_isPassengerHidden))
  2219.         {
  2220. #if ENABLE_VEHICLE_DEBUG
  2221.                 if (VehicleCVars().v_debugdraw)
  2222.                         CryLog("hiding %s during destruction of vehicle %s", pActor->GetEntity()->GetName(), m_pVehicle->GetEntity()->GetName());
  2223. #endif
  2224.  
  2225.                 pActor->GetEntity()->Hide(true);
  2226.         }
  2227.  
  2228.         // broadcast an event about the passenger exiting and that the seat is now free
  2229.         SVehicleEventParams eventParams;
  2230.         eventParams.entityId = pActor->GetEntityId();
  2231.         eventParams.iParam = m_seatId;
  2232.         m_pVehicle->BroadcastVehicleEvent(eVE_PassengerExit, eventParams);
  2233.         m_pVehicle->BroadcastVehicleEvent(eVE_SeatFreed, eventParams);
  2234.  
  2235.         if (m_pVehicle->IsEmpty())
  2236.                 m_pVehicle->StartAbandonedTimer();
  2237. }
  2238.  
  2239. //------------------------------------------------------------------------
  2240. void CVehicleSeat::UnlinkPassenger(bool ragdoll)
  2241. {
  2242.         IActorSystem* pActorSystem = CCryAction::GetCryAction()->GetIActorSystem();
  2243.         CRY_ASSERT(pActorSystem);
  2244.  
  2245.         IActor* pActor = pActorSystem->GetActor(m_passengerId);
  2246.         if (!pActor)
  2247.                 return;
  2248.  
  2249.         GivesActorSeatFeatures(false);
  2250.  
  2251.         if (m_pVehicle->GetAnimationComponent().IsEnabled())
  2252.         {
  2253.                 m_pVehicle->GetAnimationComponent().AttachPassengerScope(this, m_passengerId, false);
  2254.         }
  2255.  
  2256.         pActor->LinkToVehicle(0);
  2257.         m_passengerId = 0;
  2258.  
  2259.         if (ragdoll && gEnv->bServer && !pActor->IsGod())
  2260.         {
  2261. #if ENABLE_VEHICLE_DEBUG
  2262.                 if (VehicleCVars().v_debugdraw)
  2263.                         CryLog("%s: setting ragdoll physicalization profle", pActor->GetEntity()->GetName());
  2264. #endif
  2265.  
  2266.                 pActor->GetGameObject()->SetAspectProfile(eEA_Physics, eAP_Ragdoll);
  2267.         }
  2268.  
  2269.         m_transitionType = eVT_None;
  2270.  
  2271.         if (pActor->IsClient())
  2272.                 StopSounds();
  2273.  
  2274.         CHANGED_NETWORK_STATE(m_pVehicle, CVehicle::ASPECT_SEAT_PASSENGER);
  2275. }
  2276.  
  2277. //------------------------------------------------------------------------
  2278. bool CVehicleSeat::ProcessPassengerMovementRequest(const CMovementRequest& movementRequest)
  2279. {
  2280.         IActor* pActor = GetPassengerActor();
  2281.         if (pActor && !pActor->IsPlayer())
  2282.         {
  2283.                 if (!(m_transitionType == eVT_None || m_transitionType == eVT_RemoteUsage))
  2284.                         return false;
  2285.  
  2286.                 if (movementRequest.HasLookTarget() || movementRequest.HasAimTarget())
  2287.                 {
  2288.                         Vec3 vTurretGoal(ZERO);
  2289.  
  2290.                         if (movementRequest.HasFireTarget())
  2291.                                 vTurretGoal = movementRequest.GetFireTarget();
  2292.                         else if (movementRequest.HasAimTarget())
  2293.                                 vTurretGoal = movementRequest.GetAimTarget();
  2294.                         else if (movementRequest.HasLookTarget())
  2295.                                 vTurretGoal = movementRequest.GetLookTarget();
  2296.  
  2297.                         for (TVehicleSeatActionVector::iterator ite = m_seatActions.begin(); ite != m_seatActions.end(); ++ite)
  2298.                         {
  2299.                                 IVehicleSeatAction* pSeatAction = ite->pSeatAction;
  2300.  
  2301.                                 if (CVehicleSeatActionRotateTurret* pActionRotateTurret = CAST_VEHICLEOBJECT(CVehicleSeatActionRotateTurret, pSeatAction))
  2302.                                 {
  2303.                                         pActionRotateTurret->SetAimGoal(vTurretGoal, 1);
  2304.                                 }
  2305.  
  2306.                                 if (CVehicleSeatActionWeapons* pActionWeapons = CAST_VEHICLEOBJECT(CVehicleSeatActionWeapons, pSeatAction))
  2307.                                 {
  2308.                                         if (movementRequest.HasFireTarget())
  2309.                                                 pActionWeapons->SetFireTarget(movementRequest.GetFireTarget());
  2310.                                         else if (movementRequest.HasAimTarget())
  2311.                                                 pActionWeapons->SetFireTarget(movementRequest.GetAimTarget());
  2312.                                         else
  2313.                                                 pActionWeapons->SetFireTarget(Vec3(0, 0, 0));
  2314.                                 }
  2315.                         }
  2316.                 }
  2317.         }
  2318.  
  2319.         return true;
  2320. }
  2321.  
  2322. //------------------------------------------------------------------------
  2323. bool CVehicleSeat::RequestMovement(CMovementRequest& movementRequest)
  2324. {
  2325.         if (m_isDriver)
  2326.         {
  2327.                 if (IVehicleMovement* pMovement = m_pVehicle->GetMovement())
  2328.                         pMovement->RequestMovement(movementRequest);
  2329.         }
  2330.  
  2331.         return true;
  2332. }
  2333.  
  2334. // we use this function for computing SMovementState::eyeDirection and SMovementState::upDirecton from a transformation matrix that might hold a scaling
  2335. static Vec3 RotateAndNormalize(const Matrix34& tm, const Vec3& vectorToRotateAndNormalize)
  2336. {
  2337.         Matrix33 orientation;
  2338.         tm.GetRotation33(orientation);
  2339.         const Vec3 transformedVector = orientation * vectorToRotateAndNormalize;
  2340.         return transformedVector.GetNormalized();
  2341. }
  2342.  
  2343. //------------------------------------------------------------------------
  2344. void CVehicleSeat::GetMovementState(SMovementState& movementState)
  2345. {
  2346.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_ACTION);
  2347.  
  2348.         IEntity* pVehicleEntity = m_pVehicle->GetEntity();
  2349.         if (!pVehicleEntity)
  2350.                 return;
  2351.  
  2352.         IActor* pActor = CCryAction::GetCryAction()->GetIActorSystem()->GetActor(m_passengerId);
  2353.         IEntity* pActorEntity = pActor ? pActor->GetEntity() : NULL;
  2354.  
  2355.         const Matrix34& worldTM = pVehicleEntity->GetWorldTM();
  2356.  
  2357.         // todo: is this really intended?
  2358.         movementState.pos = worldTM.GetTranslation();
  2359.         movementState.upDirection = RotateAndNormalize(worldTM, Vec3(0, 0, 1));
  2360.         // ~todo
  2361.  
  2362.         if (m_pAimPart)
  2363.         {
  2364.                 const Matrix34& partWorldTM = m_pAimPart->GetWorldTM();
  2365.                 movementState.eyePosition = partWorldTM.GetTranslation();
  2366.                 movementState.eyeDirection = RotateAndNormalize(partWorldTM, FORWARD_DIRECTION);
  2367.         }
  2368.         else
  2369.         {
  2370.                 if (!pActor || !m_pSitHelper) // || !pActor->IsPlayer())
  2371.                 {
  2372.                         movementState.eyeDirection = RotateAndNormalize(worldTM, FORWARD_DIRECTION);
  2373.                         movementState.eyePosition = worldTM.GetTranslation();
  2374.                 }
  2375.                 else
  2376.                 {
  2377.                         Matrix34 seatWorldTM;
  2378.                         m_pSitHelper->GetWorldTM(seatWorldTM);
  2379.  
  2380.                         if (m_autoAimEnabled)
  2381.                         {
  2382.                                 const Matrix34& viewMatrix = GetISystem()->GetViewCamera().GetMatrix();
  2383.                                 movementState.eyeDirection = viewMatrix.GetColumn1(); // assumes no scaling
  2384.                                 movementState.eyePosition = viewMatrix.GetTranslation();
  2385.                         }
  2386.                         else
  2387.                         {
  2388.                                 movementState.eyeDirection = RotateAndNormalize(seatWorldTM, FORWARD_DIRECTION);
  2389.  
  2390.                                 if (pActor != NULL)
  2391.                                         movementState.eyePosition = seatWorldTM.GetTranslation() + seatWorldTM.TransformVector(pActor->GetLocalEyePos());
  2392.                                 else
  2393.                                         movementState.eyePosition = seatWorldTM.GetTranslation();
  2394.                         }
  2395.  
  2396.                 }
  2397.         }
  2398.  
  2399.         if (m_pAIVisionHelper && pActorEntity && pActorEntity->HasAI())
  2400.         {
  2401.                 const Vec3 vAIVisionHelperPos = m_pAIVisionHelper->GetWorldSpaceTranslation();
  2402.                 movementState.eyePosition = vAIVisionHelperPos;
  2403.                 movementState.weaponPosition = vAIVisionHelperPos;
  2404.         }
  2405.         else
  2406.         {
  2407.                 movementState.weaponPosition = movementState.eyePosition;
  2408.         }
  2409.  
  2410.         // this is needed for AI LookAt to work correctly
  2411.         movementState.animationEyeDirection = movementState.eyeDirection;
  2412.         //      pActor->GetLocalEyePos(0);
  2413.  
  2414.         movementState.stance = STANCE_NULL;
  2415.         movementState.atMoveTarget = false;
  2416.         pVehicleEntity->GetWorldBounds(movementState.m_StanceSize);
  2417.         movementState.m_StanceSize.Move(-movementState.pos);
  2418.         movementState.m_ColliderSize = movementState.m_StanceSize;
  2419.  
  2420.         movementState.fireDirection = movementState.eyeDirection;
  2421.         movementState.aimDirection = movementState.eyeDirection;
  2422.         movementState.entityDirection = movementState.eyeDirection;
  2423.         movementState.animationBodyDirection = movementState.eyeDirection;
  2424.         movementState.movementDirection = movementState.eyeDirection;
  2425.  
  2426.         if (IVehicleMovement* pMovement = m_pVehicle->GetMovement())
  2427.                 pMovement->GetMovementState(movementState);
  2428.  
  2429.         if (pActor)
  2430.         {
  2431.                 if (!pActor->IsPlayer() && m_pWeaponAction)
  2432.                 {
  2433.                         if (m_isDriver)
  2434.                         {
  2435.                                 movementState.fireTarget = movementState.eyePosition + 10.f * movementState.eyeDirection;
  2436.                         }
  2437.                         else
  2438.                         {
  2439.                                 Vec3 vTmp(ZERO);
  2440.                                 EntityId weaponId = m_pWeaponAction->GetWeaponEntityId(m_pWeaponAction->GetCurrentWeapon());
  2441.                                 m_pWeaponAction->GetActualWeaponDir(weaponId, 0, movementState.aimDirection, Vec3(ZERO), vTmp);
  2442.                                 m_pWeaponAction->GetFiringPos(weaponId, 0, movementState.weaponPosition);
  2443.                                 movementState.aimDirection.Normalize();
  2444.                         }
  2445.                 }
  2446.                 else if (pActor->IsClient() && pActor->IsThirdPerson())
  2447.                 {
  2448.                         movementState.weaponPosition = GetISystem()->GetViewCamera().GetPosition();
  2449.                 }
  2450.         }
  2451.  
  2452.         movementState.isAiming = true;
  2453. }
  2454.  
  2455. //------------------------------------------------------------------------
  2456. bool CVehicleSeat::GetStanceState(const SStanceStateQuery& query, SStanceState& state)
  2457. {
  2458.         IEntity* pEntity = m_pVehicle->GetEntity();
  2459.         // Returns one stance.
  2460.         if (query.stance != STANCE_STAND || !pEntity)
  2461.                 return false;
  2462.  
  2463.         // TODO: This information is very approximate at the moment.
  2464.         if (query.defaultPose)
  2465.         {
  2466.                 AABB aabb;
  2467.                 pEntity->GetLocalBounds(aabb);
  2468.  
  2469.                 state.pos.zero();
  2470.                 state.entityDirection = FORWARD_DIRECTION;
  2471.                 state.animationBodyDirection = FORWARD_DIRECTION;
  2472.                 state.upDirection(0, 0, 1);
  2473.                 state.weaponPosition.zero();
  2474.                 state.aimDirection = FORWARD_DIRECTION;
  2475.                 state.fireDirection = FORWARD_DIRECTION;
  2476.                 state.eyePosition.zero();
  2477.                 state.eyeDirection = FORWARD_DIRECTION;
  2478.                 state.m_StanceSize = aabb;
  2479.                 state.m_ColliderSize = aabb;
  2480.         }
  2481.         else
  2482.         {
  2483.                 Vec3 entityPos = pEntity->GetWorldPos();
  2484.                 Vec3 forward = pEntity->GetWorldTM().TransformVector(FORWARD_DIRECTION);
  2485.                 AABB aabb;
  2486.                 pEntity->GetWorldBounds(aabb);
  2487.                 aabb.Move(-entityPos);
  2488.  
  2489.                 state.pos = entityPos;
  2490.                 state.entityDirection = forward;
  2491.                 state.animationBodyDirection = forward;
  2492.                 state.upDirection(0, 0, 1);
  2493.                 state.weaponPosition = entityPos;
  2494.                 state.aimDirection = forward;
  2495.                 state.fireDirection = forward;
  2496.                 state.eyePosition = entityPos;
  2497.                 state.eyeDirection = forward;
  2498.                 state.m_StanceSize = aabb;
  2499.                 state.m_ColliderSize = aabb;
  2500.         }
  2501.  
  2502.         return true;
  2503. }
  2504.  
  2505. //------------------------------------------------------------------------
  2506. bool CVehicleSeat::RequestFire(bool bFire)
  2507. {
  2508.         for (TVehicleSeatActionVector::iterator ite = m_seatActions.begin(); ite != m_seatActions.end(); ++ite)
  2509.         {
  2510.                 IVehicleSeatAction* pSeatAction = ite->pSeatAction;
  2511.                 if (CVehicleSeatActionWeapons* pActionWeapons = CAST_VEHICLEOBJECT(CVehicleSeatActionWeapons, pSeatAction))
  2512.                 {
  2513.                         if (m_aiWeaponId == 0 || m_aiWeaponId == pActionWeapons->GetWeaponEntityId(0))
  2514.                         {
  2515.                                 if (bFire)
  2516.                                 {
  2517.                                         if (pActionWeapons->ForcedUsage())
  2518.                                         {
  2519.                                                 pActionWeapons->StartUsing();
  2520.                                         }
  2521.  
  2522.                                         pActionWeapons->StartFire();
  2523.                                 }
  2524.                                 else
  2525.                                 {
  2526.                                         if (pActionWeapons->ForcedUsage())
  2527.                                         {
  2528.                                                 pActionWeapons->StopUsing();
  2529.                                         }
  2530.  
  2531.                                         pActionWeapons->StopFire();
  2532.                                 }
  2533.  
  2534.                                 return true;
  2535.                         }
  2536.                 }
  2537.         }
  2538.  
  2539.         return false;
  2540. }
  2541.  
  2542. void CVehicleSeat::UpdateTargetPosAI(const Vec3& pos)
  2543. {
  2544.         const IActor* pActor = m_pGameFramework->GetIActorSystem()->GetActor(m_passengerId);
  2545.         if (pActor && pActor->IsPlayer())
  2546.         {
  2547.                 return;
  2548.         }
  2549.  
  2550.         if (m_pWeaponAction)
  2551.                 m_pWeaponAction->SetFireTarget(pos);
  2552. }
  2553.  
  2554. //------------------------------------------------------------------------
  2555. TVehicleSeatId CVehicleSeat::GetNextSeatId(const TVehicleSeatId currentSeatId) const
  2556. {
  2557.         return m_pVehicle->GetNextSeatId(currentSeatId);
  2558. }
  2559.  
  2560. //------------------------------------------------------------------------
  2561. CGameChannel* CVehicleSeat::GetGameChannel(EntityId actorId)
  2562. {
  2563.         IActor* pActor = m_pGameFramework->GetIActorSystem()->GetActor(actorId);
  2564.         if (pActor)
  2565.         {
  2566.                 int channelId = pActor->GetChannelId();
  2567.                 if (channelId)
  2568.                 {
  2569.                         CGameServerNub* pServerNub = CCryAction::GetCryAction()->GetGameServerNub();
  2570.                         return pServerNub->GetChannel(channelId);
  2571.                 }
  2572.         }
  2573.  
  2574.         return 0;
  2575. }
  2576.  
  2577. //------------------------------------------------------------------------
  2578. void CVehicleSeat::OnVehicleEvent(EVehicleEvent event, const SVehicleEventParams& params)
  2579. {
  2580.         // NB: seat actions which require events should register themselves as vehicle listeners,
  2581.         //      to avoid calling all of them from here.
  2582.  
  2583.         switch (event)
  2584.         {
  2585.         case eVE_Destroyed:
  2586.                 {
  2587.                         if (m_passengerId)
  2588.                         {
  2589.                                 if (!IsRemoteControlledInternal())
  2590.                                 {
  2591.                                         // kill non-dead passengers
  2592.                                         IActor* pActor = m_pGameFramework->GetIActorSystem()->GetActor(m_passengerId);
  2593.                                         if (!pActor)
  2594.                                                 return;
  2595.  
  2596.                                         if (gEnv->bServer && !pActor->IsDead())
  2597.                                         {
  2598.                                                 IGameRules* pGameRules = m_pGameFramework->GetIGameRulesSystem()->GetCurrentGameRules();
  2599.                                                 if (pGameRules)
  2600.                                                 {
  2601.                                                         HitInfo hit;
  2602.  
  2603.                                                         EntityId shooterId = params.entityId;
  2604.                                                         if (shooterId == m_pVehicle->GetEntityId())
  2605.                                                         {
  2606.                                                                 if (m_pVehicle->GetDriver())
  2607.                                                                         shooterId = m_pVehicle->GetDriver()->GetEntityId();
  2608.                                                         }
  2609.  
  2610.                                                         hit.targetId = m_passengerId;
  2611.                                                         hit.shooterId = shooterId;
  2612.                                                         hit.weaponId = m_pVehicle->GetEntityId();
  2613.                                                         hit.damage = gEnv->bMultiplayer ? 1000.0f : 1000000.0f;
  2614.                                                         hit.type = CVehicle::s_vehicleDestructionTypeId;
  2615.                                                         hit.pos = pActor->GetEntity()->GetWorldPos();
  2616.  
  2617.                                                         pGameRules->ServerHit(hit);
  2618.                                                 }
  2619.                                         }
  2620.                                         else
  2621.                                         {
  2622.                                                 if (!pActor->IsPlayer())
  2623.                                                 {
  2624.                                                         Exit(false, true);
  2625.                                                         if (m_pVehicle->GetMovement() && m_pVehicle->GetMovement()->GetMovementType() == IVehicleMovement::eVMT_Air)
  2626.                                                         {
  2627.                                                                 pActor->HolsterItem(false);
  2628.                                                                 pActor->GetEntity()->Hide(true);
  2629.                                                         }
  2630.                                                 }
  2631.                                         }
  2632.                                 }
  2633.                                 else
  2634.                                 {
  2635.                                         Exit(false, true);
  2636.                                 }
  2637.                         }
  2638.                 }
  2639.                 break;
  2640.         case eVE_ToggleDriverControlledGuns:
  2641.                 {
  2642.                         if (!params.bParam)
  2643.                         {
  2644.                                 if (m_passengerId && m_transitionType == eVT_RemoteUsage && IsGunner())
  2645.                                 {
  2646.                                         ExitRemotely();
  2647.  
  2648.                                         if (GetCurrentViewId() > FirstVehicleViewId) //? should it mean if it is not the FirstVehicleViewId?
  2649.                                                 SetView(FirstVehicleViewId);
  2650.                                 }
  2651.                         }
  2652.                         else
  2653.                         {
  2654.                                 if (m_passengerId && IsDriver())
  2655.                                 {
  2656.                                         if (CVehicleSeat* pSeat = GetSeatUsedRemotely(false))
  2657.                                         {
  2658.                                                 if (!pSeat->GetPassenger(true))
  2659.                                                 {
  2660.                                                         pSeat->EnterRemotely(m_passengerId);
  2661.  
  2662.                                                         if (GetCurrentViewId() > FirstVehicleViewId) //? should it mean if it is not the FirstVehicleViewId?
  2663.                                                                 SetView(FirstVehicleViewId);
  2664.                                                 }
  2665.                                         }
  2666.                                 }
  2667.                         }
  2668.                 }
  2669.                 break;
  2670.         case eVE_SeatFreed:
  2671.                 OnSeatFreed(params.iParam, params.entityId);
  2672.             &