BVB Source Codes

CRYENGINE Show FlowNodesAIActionSequence.cpp Source code

Return Download CRYENGINE: download FlowNodesAIActionSequence.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. // -------------------------------------------------------------------------
  4. //  File name:   FlowNodesAIActionSequence.cpp
  5. //  Version:     v1.00
  6. //  Created:     2014-04-29 by Christian Werle.
  7. //  Description: A bunch of FlowNodes that are AI-Sequence-compatible and can only be instantiated from within such one.
  8. //               Having them AI-Sequence-compatible is an "intended restriction" for a higher-level decision system to manage
  9. //               what is currently executing on an AI in a more controllable way which ultimately boils down to being able to
  10. //               distinguish between autonomous behavior vs. scripting via FlowNodes.
  11. // -------------------------------------------------------------------------
  12. //  History:
  13. //
  14. ////////////////////////////////////////////////////////////////////////////
  15.  
  16. #include "StdAfx.h"
  17. #include "VehicleSystem/VehicleSeat.h"
  18. #include "VehicleSystem/VehicleCVars.h"
  19. #include "VehicleSystem/Vehicle.h"
  20. #include "VehicleSystem/VehicleSeatActionRotateTurret.h"
  21.  
  22. #include <CryAISystem/IAIActionSequence.h>
  23. #include <CryAISystem/IMovementSystem.h>
  24. #include <CryAISystem/MovementRequest.h>
  25. #include <CryFlowGraph/IFlowBaseNode.h>
  26.  
  27. //////////////////////////////////////////////////////////////////////////
  28. //
  29. // CryAction_AIActionSequenceFlowNodeBase
  30. //
  31. //////////////////////////////////////////////////////////////////////////
  32. class CryAction_AIActionSequenceFlowNodeBase    // prefixed with "CryAction" to prevent naming clashes in monolithic builds
  33.         : public CFlowBaseNode<eNCT_Instanced>
  34.           , public AIActionSequence::SequenceActionBase
  35. {
  36. protected:
  37.         CryAction_AIActionSequenceFlowNodeBase();
  38.         void FinishSequenceActionAndActivateOutputPort(int port);
  39.         void CancelSequenceAndActivateOutputPort(int port);
  40.  
  41.         SActivationInfo m_actInfo;
  42.         bool            m_stopFlowGraphNodeFromGettingUpdatedWhenSequenceActionFinishesOrCancels; // just a convenient way for derived classes to stop updating the FG node when the AISequence-Action gets finished or canceled in many different places
  43.  
  44. private:
  45.         void SequenceActionFinishedOrCanceled();
  46. };
  47.  
  48. CryAction_AIActionSequenceFlowNodeBase::CryAction_AIActionSequenceFlowNodeBase()
  49. {
  50.         m_stopFlowGraphNodeFromGettingUpdatedWhenSequenceActionFinishesOrCancels = false;
  51. }
  52.  
  53. void CryAction_AIActionSequenceFlowNodeBase::FinishSequenceActionAndActivateOutputPort(int port)
  54. {
  55.         gEnv->pAISystem->GetSequenceManager()->ActionCompleted(GetAssignedSequenceId());
  56.         SequenceActionFinishedOrCanceled();
  57.         ActivateOutput(&m_actInfo, port, true);
  58. }
  59.  
  60. void CryAction_AIActionSequenceFlowNodeBase::CancelSequenceAndActivateOutputPort(int port)
  61. {
  62.         gEnv->pAISystem->GetSequenceManager()->CancelSequence(GetAssignedSequenceId());
  63.         SequenceActionFinishedOrCanceled();
  64.         ActivateOutput(&m_actInfo, port, true);
  65. }
  66.  
  67. void CryAction_AIActionSequenceFlowNodeBase::SequenceActionFinishedOrCanceled()
  68. {
  69.         if (m_stopFlowGraphNodeFromGettingUpdatedWhenSequenceActionFinishesOrCancels && m_actInfo.pGraph)
  70.         {
  71.                 m_actInfo.pGraph->SetRegularlyUpdated(m_actInfo.myID, false);
  72.         }
  73. }
  74.  
  75. //////////////////////////////////////////////////////////////////////////
  76. //
  77. // CFlowNode_AISequenceAction_ApproachAndEnterVehicle
  78. //
  79. //////////////////////////////////////////////////////////////////////////
  80. class CFlowNode_AISequenceAction_ApproachAndEnterVehicle
  81.         : public CryAction_AIActionSequenceFlowNodeBase
  82.           , public IVehicleEventListener
  83. {
  84. public:
  85.         CFlowNode_AISequenceAction_ApproachAndEnterVehicle(SActivationInfo* pActInfo);
  86.         ~CFlowNode_AISequenceAction_ApproachAndEnterVehicle();
  87.  
  88.         // IFlowNode
  89.         virtual IFlowNodePtr Clone(SActivationInfo* pActInfo);
  90.         virtual void         GetConfiguration(SFlowNodeConfig& config);
  91.         virtual void         ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo);
  92.         virtual void         GetMemoryUsage(ICrySizer* sizer) const;
  93.         // ~IFlowNode
  94.  
  95.         // AIActionSequence::SequenceActionBase
  96.         virtual void HandleSequenceEvent(AIActionSequence::SequenceEvent sequenceEvent);
  97.         // ~AIActionSequence::SequenceActionBase
  98.  
  99.         // IVehicleEventListener
  100.         virtual void OnVehicleEvent(EVehicleEvent event, const SVehicleEventParams& params);
  101.         // ~IVehicleEventListener
  102.  
  103. private:
  104.         enum
  105.         {
  106.                 InputPort_Start,
  107.                 InputPort_VehicleId,
  108.                 InputPort_Seat,
  109.                 InputPort_Speed,
  110.                 InputPort_Stance,
  111.                 InputPort_Fast,
  112.         };
  113.  
  114.         enum
  115.         {
  116.                 OutputPort_Done
  117.         };
  118.  
  119.         IEntity*      GetEntity();
  120.         IVehicle*     GetVehicle(bool alsoCheckForCrewHostility);
  121.         IVehicleSeat* GetVehicleSeat(IVehicle* pVehicleHint);
  122.         bool          GetAnimationTransitionEnabled() const;
  123.         void          MovementRequestCallback(const MovementRequestResult& result);
  124.         void          TeleportToVehicleSeat();
  125.         void          EnterVehicleSeat(bool animationTransitionEnabled, IVehicleSeat* pVehicleSeatHint);
  126.         void          UnregisterFromVehicleEvent(IVehicleSeat* pVehicleSeatHint);
  127.  
  128.         EntityId          m_entityId;
  129.         EntityId          m_vehicleId;
  130.         int               m_seatNumber;
  131.         Vec3              m_vehicleSeatEnterPosition;
  132.         MovementRequestID m_movementRequestID;  // used for moving to the vehicle seat that we wanna enter
  133.         bool              m_fast;               // if true: skip approaching and enter-animation
  134. };
  135.  
  136. CFlowNode_AISequenceAction_ApproachAndEnterVehicle::CFlowNode_AISequenceAction_ApproachAndEnterVehicle(SActivationInfo* pActInfo)
  137.         : m_entityId(0)
  138.         , m_vehicleId(0)
  139.         , m_seatNumber(0)
  140.         , m_vehicleSeatEnterPosition(ZERO)
  141.         , m_fast(false)
  142. {
  143. }
  144.  
  145. CFlowNode_AISequenceAction_ApproachAndEnterVehicle::~CFlowNode_AISequenceAction_ApproachAndEnterVehicle()
  146. {
  147. }
  148.  
  149. IFlowNodePtr CFlowNode_AISequenceAction_ApproachAndEnterVehicle::Clone(SActivationInfo* pActInfo)
  150. {
  151.         return new CFlowNode_AISequenceAction_ApproachAndEnterVehicle(pActInfo);
  152. }
  153.  
  154. void CFlowNode_AISequenceAction_ApproachAndEnterVehicle::GetConfiguration(SFlowNodeConfig& config)
  155. {
  156.         static const SInputPortConfig inputPortConfig[] =
  157.         {
  158.                 InputPortConfig_Void("Start"),
  159.                 InputPortConfig<EntityId>("VehicleId",_HELP("Vehicle to be entered")),
  160.                 InputPortConfig<string>("SeatNumber", _HELP("Seat to be entered"),                       _HELP("Seat"),_UICONFIG("dt=vehicleSeats, ref_entity=VehicleId")),
  161.                 InputPortConfig<int>("Speed",         _HELP("Speed to approach the vehicle with"),       NULL,      _UICONFIG("enum_int:Walk=0,Run=1,Sprint=2")),
  162.                 InputPortConfig<int>("Stance",        _HELP("Stance while approaching the vehicle"),     NULL,      _UICONFIG("enum_int:Relaxed=0,Alert=1,Combat=2")),
  163.                 InputPortConfig<bool>("Fast",         _HELP("Skip approaching and entering animation")),
  164.                 { 0 }
  165.         };
  166.  
  167.         static const SOutputPortConfig outputPortConfig[] =
  168.         {
  169.                 OutputPortConfig_Void("Done"),
  170.                 { 0 }
  171.         };
  172.  
  173.         config.pInputPorts = inputPortConfig;
  174.         config.pOutputPorts = outputPortConfig;
  175.         config.sDescription = _HELP("Allows the AI agent to move to the specified vehicle and to then enter the specified seat");
  176.         config.nFlags |= EFLN_TARGET_ENTITY | EFLN_AISEQUENCE_ACTION;
  177.         config.SetCategory(EFLN_APPROVED);
  178. }
  179.  
  180. void CFlowNode_AISequenceAction_ApproachAndEnterVehicle::ProcessEvent(IFlowNode::EFlowEvent event, IFlowNode::SActivationInfo* pActInfo)
  181. {
  182.         if (!pActInfo->pEntity)
  183.                 return;
  184.  
  185.         switch (event)
  186.         {
  187.         case eFE_Activate:
  188.                 {
  189.                         m_actInfo = *pActInfo;
  190.                         m_stopFlowGraphNodeFromGettingUpdatedWhenSequenceActionFinishesOrCancels = true;
  191.                         m_movementRequestID = MovementRequestID::Invalid();
  192.  
  193.                         if (IsPortActive(pActInfo, InputPort_Start))
  194.                         {
  195.                                 if (const AIActionSequence::SequenceId assignedSequenceId = GetAssignedSequenceId())
  196.                                 {
  197.                                         gEnv->pAISystem->GetSequenceManager()->RequestActionStart(assignedSequenceId, pActInfo->myID);
  198.                                         m_actInfo.pGraph->SetRegularlyUpdated(m_actInfo.myID, true);
  199.                                 }
  200.                         }
  201.                 }
  202.                 break;
  203.         }
  204. }
  205.  
  206. void CFlowNode_AISequenceAction_ApproachAndEnterVehicle::GetMemoryUsage(ICrySizer* sizer) const
  207. {
  208.         sizer->Add(*this);
  209. }
  210.  
  211. void CFlowNode_AISequenceAction_ApproachAndEnterVehicle::HandleSequenceEvent(AIActionSequence::SequenceEvent sequenceEvent)
  212. {
  213.         switch (sequenceEvent)
  214.         {
  215.         case AIActionSequence::StartAction:
  216.                 {
  217.                         if (!m_actInfo.pEntity)
  218.                         {
  219.                                 // the entity has gone for some reason, at least make sure the action gets finished properly and the FG continues
  220.                                 UnregisterFromVehicleEvent(NULL);
  221.                                 CancelSequenceAndActivateOutputPort(OutputPort_Done);
  222.                                 return;
  223.                         }
  224.  
  225.                         m_entityId = m_actInfo.pEntity->GetId();
  226.                         m_vehicleId = GetPortEntityId(&m_actInfo, InputPort_VehicleId);
  227.                         m_fast = GetPortBool(&m_actInfo, InputPort_Fast);
  228.  
  229.                         const bool alsoCheckForCrewHostility = true;
  230.                         IVehicle* pVehicle = GetVehicle(alsoCheckForCrewHostility);
  231.                         if (!pVehicle)
  232.                         {
  233.                                 CryLog("Actor %s failed to enter vehicle (specified vehicle not found or its crew is hostile towards the actor returned true)", m_actInfo.pEntity->GetName());
  234.                                 CancelSequenceAndActivateOutputPort(OutputPort_Done);
  235.                                 return;
  236.                         }
  237.  
  238.                         m_seatNumber = pVehicle->GetSeatId(GetPortString(&m_actInfo, InputPort_Seat));
  239.                         IVehicleSeat* pSeat = GetVehicleSeat(pVehicle);
  240.                         if (!pSeat)
  241.                         {
  242.                                 CryLog("Actor %s failed to enter vehicle (bad seat number provided: %i)", m_actInfo.pEntity->GetName(), m_seatNumber);
  243.                                 CancelSequenceAndActivateOutputPort(OutputPort_Done);
  244.                                 return;
  245.                         }
  246.  
  247.                         const IVehicleHelper* pEnterHelper = static_cast<CVehicleSeat*>(pSeat)->GetEnterHelper();
  248.                         if (!pEnterHelper)
  249.                         {
  250.                                 CryLog("Actor %s failed to enter vehicle (vehicle has no enter-helper)", m_actInfo.pEntity->GetName());
  251.                                 CancelSequenceAndActivateOutputPort(OutputPort_Done);
  252.                                 return;
  253.                         }
  254.  
  255.                         m_vehicleSeatEnterPosition = pEnterHelper->GetWorldSpaceTranslation();
  256.  
  257.                         assert(gEnv && gEnv->pGameFramework && gEnv->pGameFramework->GetIActorSystem());
  258.                         IActor* pActor = gEnv->pGameFramework->GetIActorSystem()->GetActor(m_actInfo.pEntity->GetId());
  259.  
  260.                         // if it's the player, have him enter quickly (we assume that the user moved him close enough to the vehicle)
  261.                         if (pActor && pActor->IsPlayer())
  262.                         {
  263.                                 EnterVehicleSeat(true, pSeat);
  264.                         }
  265.                         else if (m_actInfo.pEntity->GetAI())
  266.                         {
  267.                                 if (m_fast)
  268.                                 {
  269.                                         TeleportToVehicleSeat();
  270.                                         EnterVehicleSeat(false, pSeat);
  271.                                 }
  272.                                 else
  273.                                 {
  274.                                         MovementRequest request;
  275.                                         request.callback = functor(*this, &CFlowNode_AISequenceAction_ApproachAndEnterVehicle::MovementRequestCallback);
  276.                                         request.entityID = m_actInfo.pEntity->GetId();
  277.                                         request.type = MovementRequest::MoveTo;
  278.                                         request.destination = m_vehicleSeatEnterPosition;
  279.                                         request.style.SetSpeed((MovementStyle::Speed)GetPortInt(&m_actInfo, InputPort_Speed));
  280.                                         request.style.SetStance((MovementStyle::Stance)GetPortInt(&m_actInfo, InputPort_Stance));
  281.                                         m_movementRequestID = gEnv->pAISystem->GetMovementSystem()->QueueRequest(request);
  282.                                 }
  283.                         }
  284.                         else if (pActor)
  285.                         {
  286.                                 pActor->HolsterItem(true);
  287.                                 pActor->MountedGunControllerEnabled(false);
  288.                                 pActor->GetGameObject()->SetAspectProfile(eEA_Physics, eAP_Alive);
  289.                                 TeleportToVehicleSeat();
  290.                                 EnterVehicleSeat(GetAnimationTransitionEnabled(), pSeat);
  291.                         }
  292.                         else
  293.                         {
  294.                                 CRY_ASSERT_MESSAGE(0, "no compatible entity was provided");
  295.                                 CryWarning(VALIDATOR_MODULE_AI, VALIDATOR_WARNING, "Actor %s failed to enter vehicle (no compatible entity was provided)", m_actInfo.pEntity->GetName());
  296.                                 CancelSequenceAndActivateOutputPort(OutputPort_Done);
  297.                         }
  298.                 }
  299.                 break;
  300.  
  301.         case AIActionSequence::SequenceStopped:
  302.                 {
  303.                         if (m_movementRequestID)
  304.                         {
  305.                                 gEnv->pAISystem->GetMovementSystem()->CancelRequest(m_movementRequestID);
  306.                                 m_movementRequestID = MovementRequestID::Invalid();
  307.                                 UnregisterFromVehicleEvent(NULL);
  308.                         }
  309.                 }
  310.                 break;
  311.         }
  312. }
  313.  
  314. IEntity* CFlowNode_AISequenceAction_ApproachAndEnterVehicle::GetEntity()
  315. {
  316.         assert(gEnv && gEnv->pEntitySystem);
  317.         return gEnv->pEntitySystem->GetEntity(m_entityId);
  318. }
  319.  
  320. IVehicle* CFlowNode_AISequenceAction_ApproachAndEnterVehicle::GetVehicle(bool alsoCheckForCrewHostility)
  321. {
  322.         if (!m_vehicleId)
  323.                 return NULL;
  324.  
  325.         assert(gEnv && gEnv->pGameFramework && gEnv->pGameFramework->GetIVehicleSystem());
  326.         IVehicle* pVehicle = gEnv->pGameFramework->GetIVehicleSystem()->GetVehicle(m_vehicleId);
  327.         if (!pVehicle)
  328.                 return NULL;
  329.  
  330.         if (alsoCheckForCrewHostility && pVehicle->IsCrewHostile(m_entityId))
  331.                 return NULL;
  332.  
  333.         return pVehicle;
  334. }
  335.  
  336. IVehicleSeat* CFlowNode_AISequenceAction_ApproachAndEnterVehicle::GetVehicleSeat(IVehicle* pVehicleHint)
  337. {
  338.         if (!pVehicleHint)
  339.         {
  340.                 const bool alsoCheckForCrewHostility = false;
  341.                 pVehicleHint = GetVehicle(alsoCheckForCrewHostility);
  342.         }
  343.         return pVehicleHint ? pVehicleHint->GetSeatById(m_seatNumber) : NULL;
  344. }
  345.  
  346. bool CFlowNode_AISequenceAction_ApproachAndEnterVehicle::GetAnimationTransitionEnabled() const
  347. {
  348.         bool transitionEnabled = !m_fast;
  349.  
  350.         // check for suppressed animation transition via cvar v_transitionAnimations
  351.         if (VehicleCVars().v_transitionAnimations == 0)
  352.                 transitionEnabled = false;
  353.  
  354.         return transitionEnabled;
  355. }
  356.  
  357. void CFlowNode_AISequenceAction_ApproachAndEnterVehicle::MovementRequestCallback(const MovementRequestResult& result)
  358. {
  359.         assert(m_movementRequestID == result.requestID);
  360.  
  361.         switch (result.result)
  362.         {
  363.         case MovementRequestResult::Failure:
  364.                 {
  365.                         // could not reach the vehicle seat (probably no path found)
  366.                         // => just teleport there
  367.                         TeleportToVehicleSeat();
  368.                 }
  369.         // fall through
  370.         case MovementRequestResult::ReachedDestination:
  371.                 {
  372.                         m_movementRequestID = MovementRequestID::Invalid();
  373.                         EnterVehicleSeat(GetAnimationTransitionEnabled(), NULL);
  374.                 }
  375.                 break;
  376.         }
  377. }
  378.  
  379. void CFlowNode_AISequenceAction_ApproachAndEnterVehicle::TeleportToVehicleSeat()
  380. {
  381.         if (IEntity* pEntity = GetEntity())
  382.         {
  383.                 Matrix34 transform = pEntity->GetWorldTM();
  384.                 transform.SetTranslation(m_vehicleSeatEnterPosition);
  385.                 pEntity->SetWorldTM(transform);
  386.         }
  387. }
  388.  
  389. void CFlowNode_AISequenceAction_ApproachAndEnterVehicle::EnterVehicleSeat(bool animationTransitionEnabled, IVehicleSeat* pVehicleSeatHint)
  390. {
  391.         if (!pVehicleSeatHint)
  392.                 pVehicleSeatHint = GetVehicleSeat(NULL);
  393.  
  394.         if (pVehicleSeatHint)
  395.         {
  396.                 pVehicleSeatHint->GetVehicle()->RegisterVehicleEventListener(this, "CFlowNode_AISequenceAction_ApproachAndEnterVehicle");
  397.                 pVehicleSeatHint->Enter(m_entityId, animationTransitionEnabled);
  398.         }
  399.         else
  400.         {
  401.                 // prematurely finish the action as the seat or entity has magically disappeared
  402.                 CancelSequenceAndActivateOutputPort(OutputPort_Done);
  403.         }
  404. }
  405.  
  406. void CFlowNode_AISequenceAction_ApproachAndEnterVehicle::UnregisterFromVehicleEvent(IVehicleSeat* pVehicleSeatHint)
  407. {
  408.         IVehicle* pVehicle = NULL;
  409.  
  410.         if (pVehicleSeatHint)
  411.         {
  412.                 pVehicle = pVehicleSeatHint->GetVehicle();
  413.         }
  414.         else
  415.         {
  416.                 const bool alsoCheckForCrewHostility = false;
  417.                 pVehicle = GetVehicle(alsoCheckForCrewHostility);
  418.         }
  419.  
  420.         if (pVehicle)
  421.         {
  422.                 pVehicle->UnregisterVehicleEventListener(this);
  423.         }
  424. }
  425.  
  426. void CFlowNode_AISequenceAction_ApproachAndEnterVehicle::OnVehicleEvent(EVehicleEvent event, const SVehicleEventParams& params)
  427. {
  428.         if (event == eVE_PassengerEnter)
  429.         {
  430.                 UnregisterFromVehicleEvent(NULL);
  431.                 FinishSequenceActionAndActivateOutputPort(OutputPort_Done);
  432.         }
  433. }
  434.  
  435. //////////////////////////////////////////////////////////////////////////
  436. //
  437. // CFlowNode_AISequenceAction_VehicleRotateTurret
  438. //
  439. //////////////////////////////////////////////////////////////////////////
  440. class CFlowNode_AISequenceAction_VehicleRotateTurret
  441.         : public CryAction_AIActionSequenceFlowNodeBase
  442. {
  443. public:
  444.         CFlowNode_AISequenceAction_VehicleRotateTurret(SActivationInfo* pActInfo);
  445.         ~CFlowNode_AISequenceAction_VehicleRotateTurret();
  446.  
  447.         // IFlowNode
  448.         virtual IFlowNodePtr Clone(SActivationInfo* pActInfo);
  449.         virtual void         GetConfiguration(SFlowNodeConfig& config);
  450.         virtual void         ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo);
  451.         virtual void         GetMemoryUsage(ICrySizer* sizer) const;
  452.         // ~IFlowNode
  453.  
  454.         // AIActionSequence::SequenceActionBase
  455.         virtual void HandleSequenceEvent(AIActionSequence::SequenceEvent sequenceEvent);
  456.         // ~AIActionSequence::SequenceActionBase
  457.  
  458. private:
  459.         enum
  460.         {
  461.                 InputPort_Start,
  462.                 InputPort_AimPos,
  463.                 InputPort_ThresholdPitch,
  464.                 InputPort_ThresholdYaw
  465.         };
  466.  
  467.         enum
  468.         {
  469.                 OutputPort_Done
  470.         };
  471.  
  472.         CVehicleSeatActionRotateTurret* m_pActionRotateTurret;
  473.         float                           m_pitchThreshold;
  474.         float                           m_yawThreshold;
  475. };
  476.  
  477. CFlowNode_AISequenceAction_VehicleRotateTurret::CFlowNode_AISequenceAction_VehicleRotateTurret(SActivationInfo* pActInfo)
  478.         : m_pActionRotateTurret(NULL)
  479.         , m_pitchThreshold(0.0f)
  480.         , m_yawThreshold(0.0f)
  481. {
  482. }
  483.  
  484. CFlowNode_AISequenceAction_VehicleRotateTurret::~CFlowNode_AISequenceAction_VehicleRotateTurret()
  485. {
  486. }
  487.  
  488. IFlowNodePtr CFlowNode_AISequenceAction_VehicleRotateTurret::Clone(SActivationInfo* pActInfo)
  489. {
  490.         return new CFlowNode_AISequenceAction_VehicleRotateTurret(pActInfo);
  491. }
  492.  
  493. void CFlowNode_AISequenceAction_VehicleRotateTurret::GetConfiguration(SFlowNodeConfig& config)
  494. {
  495.         static const SInputPortConfig inputPortConfig[] =
  496.         {
  497.                 InputPortConfig_Void("Start"),
  498.                 InputPortConfig<Vec3>("AimPos",         _HELP("Position to aim at with the turret")),
  499.                 InputPortConfig<float>("ThresholdPitch",_HELP("Threshold of the pitch angle (in degrees) before triggering the output port. Must be used in conjunction with the ThresholdYaw input port.")),
  500.                 InputPortConfig<float>("ThresholdYaw",  _HELP("Threshold of the yaw angle (in degrees) before triggering the output port. Must be used in conjunction with the ThresholdPitch input port.")),
  501.                 { 0 }
  502.         };
  503.  
  504.         static const SOutputPortConfig outputPortConfig[] =
  505.         {
  506.                 OutputPortConfig_Void("Done"),
  507.                 { 0 }
  508.         };
  509.  
  510.         config.pInputPorts = inputPortConfig;
  511.         config.pOutputPorts = outputPortConfig;
  512.         config.sDescription = _HELP("Allows an AI agent to align the vehicle's turret to an aiming position.");
  513.         config.nFlags |= EFLN_TARGET_ENTITY | EFLN_AISEQUENCE_ACTION;
  514.         config.SetCategory(EFLN_APPROVED);
  515. }
  516.  
  517. void CFlowNode_AISequenceAction_VehicleRotateTurret::ProcessEvent(IFlowNode::EFlowEvent event, IFlowNode::SActivationInfo* pActInfo)
  518. {
  519.         if (!pActInfo->pEntity)
  520.                 return;
  521.  
  522.         switch (event)
  523.         {
  524.         case eFE_Activate:
  525.                 {
  526.                         m_actInfo = *pActInfo;
  527.                         m_stopFlowGraphNodeFromGettingUpdatedWhenSequenceActionFinishesOrCancels = true;
  528.                         m_pActionRotateTurret = NULL;
  529.  
  530.                         if (IsPortActive(pActInfo, InputPort_Start))
  531.                         {
  532.                                 if (const AIActionSequence::SequenceId assignedSequenceId = GetAssignedSequenceId())
  533.                                 {
  534.                                         gEnv->pAISystem->GetSequenceManager()->RequestActionStart(assignedSequenceId, pActInfo->myID);
  535.                                         m_actInfo.pGraph->SetRegularlyUpdated(m_actInfo.myID, true);
  536.                                 }
  537.                         }
  538.                 }
  539.                 break;
  540.  
  541.         case eFE_Update:
  542.                 {
  543.                         if (m_pActionRotateTurret)
  544.                         {
  545.                                 float pitch, yaw;
  546.                                 m_pActionRotateTurret->GetRemainingAnglesToAimGoalInDegrees(pitch, yaw);
  547.                                 if (fabsf(pitch) <= m_pitchThreshold && fabs(yaw) <= m_yawThreshold)
  548.                                 {
  549.                                         FinishSequenceActionAndActivateOutputPort(OutputPort_Done);
  550.                                 }
  551.                         }
  552.                 }
  553.                 break;
  554.         }
  555. }
  556.  
  557. void CFlowNode_AISequenceAction_VehicleRotateTurret::GetMemoryUsage(ICrySizer* sizer) const
  558. {
  559.         sizer->Add(*this);
  560. }
  561.  
  562. void CFlowNode_AISequenceAction_VehicleRotateTurret::HandleSequenceEvent(AIActionSequence::SequenceEvent sequenceEvent)
  563. {
  564.         switch (sequenceEvent)
  565.         {
  566.         case AIActionSequence::StartAction:
  567.                 {
  568.                         if (!m_actInfo.pEntity)
  569.                         {
  570.                                 // the entity has gone for some reason, at least make sure the action gets finished properly and the FG continues
  571.                                 CancelSequenceAndActivateOutputPort(OutputPort_Done);
  572.                                 return;
  573.                         }
  574.  
  575.                         assert(gEnv && gEnv->pGameFramework && gEnv->pGameFramework->GetIActorSystem());
  576.                         IActor* pActor = gEnv->pGameFramework->GetIActorSystem()->GetActor(m_actInfo.pEntity->GetId());
  577.  
  578.                         // ensure the FG entity is an IActor
  579.                         if (!pActor)
  580.                         {
  581.                                 CRY_ASSERT_MESSAGE(0, "no compatible entity was provided");
  582.                                 CryWarning(VALIDATOR_MODULE_AI, VALIDATOR_WARNING, "Actor %s failed to enter vehicle (no compatible entity was provided)", m_actInfo.pEntity->GetName());
  583.                                 CancelSequenceAndActivateOutputPort(OutputPort_Done);
  584.                                 return;
  585.                         }
  586.  
  587.                         // get the vehicle the actor is linked to
  588.                         IVehicle* pVehicle = pActor->GetLinkedVehicle();
  589.                         if (!pVehicle)
  590.                         {
  591.                                 CRY_ASSERT_MESSAGE(0, "agent is not linked to a vehicle");
  592.                                 CryWarning(VALIDATOR_MODULE_AI, VALIDATOR_WARNING, "Actor %s is not linked to a vehicle", m_actInfo.pEntity->GetName());
  593.                                 CancelSequenceAndActivateOutputPort(OutputPort_Done);
  594.                                 return;
  595.                         }
  596.  
  597.                         // get the seat the actor is sitting on
  598.                         CVehicleSeat* pSeat = static_cast<CVehicleSeat*>(pVehicle->GetSeatForPassenger(m_actInfo.pEntity->GetId()));
  599.                         if (!pSeat)
  600.                         {
  601.                                 CRY_ASSERT_MESSAGE(0, "agent is not sitting in the vehicle it is linked to");
  602.                                 CryWarning(VALIDATOR_MODULE_AI, VALIDATOR_WARNING, "Actor %s is not sitting in the vehicle it is linked to", m_actInfo.pEntity->GetName());
  603.                                 CancelSequenceAndActivateOutputPort(OutputPort_Done);
  604.                                 return;
  605.                         }
  606.  
  607.                         // scan for the seat-action that allows rotating the turret
  608.                         TVehicleSeatActionVector& seatActions = pSeat->GetSeatActions();
  609.                         for (TVehicleSeatActionVector::iterator it = seatActions.begin(); it != seatActions.end(); ++it)
  610.                         {
  611.                                 IVehicleSeatAction* pSeatAction = it->pSeatAction;
  612.                                 if ((m_pActionRotateTurret = CAST_VEHICLEOBJECT(CVehicleSeatActionRotateTurret, pSeatAction)))
  613.                                 {
  614.                                         break;
  615.                                 }
  616.                         }
  617.  
  618.                         // ensure the vehicle-seat provided the correct action
  619.                         if (!m_pActionRotateTurret)
  620.                         {
  621.                                 CRY_ASSERT_MESSAGE(0, "a CVehicleSeatActionRotateTurret is not provided by the vehicle or someone else in the vehicle has reserved that action already.");
  622.                                 CryWarning(VALIDATOR_MODULE_AI, VALIDATOR_WARNING, "Actor %s could not find a CVehicleSeatActionRotateTurret or that action is already reserved by someone else", m_actInfo.pEntity->GetName());
  623.                                 CancelSequenceAndActivateOutputPort(OutputPort_Done);
  624.                                 return;
  625.                         }
  626.  
  627.                         m_pitchThreshold = GetPortFloat(&m_actInfo, InputPort_ThresholdPitch);
  628.                         m_yawThreshold = GetPortFloat(&m_actInfo, InputPort_ThresholdYaw);
  629.  
  630.                         Vec3 aimPos = GetPortVec3(&m_actInfo, InputPort_AimPos);
  631.                         m_pActionRotateTurret->SetAimGoal(aimPos);
  632.                 }
  633.                 break;
  634.  
  635.         case AIActionSequence::SequenceStopped:
  636.                 {
  637.                         if (m_pActionRotateTurret)
  638.                         {
  639.                                 // cancel the rotation action
  640.                                 m_pActionRotateTurret->SetAimGoal(Vec3Constants<float>::fVec3_Zero);
  641.                                 m_pActionRotateTurret = NULL;
  642.                         }
  643.                 }
  644.                 break;
  645.         }
  646. }
  647.  
  648. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  649.  
  650. REGISTER_FLOW_NODE("AISequence:ApproachAndEnterVehicle", CFlowNode_AISequenceAction_ApproachAndEnterVehicle)
  651. REGISTER_FLOW_NODE("AISequence:VehicleRotateTurret", CFlowNode_AISequenceAction_VehicleRotateTurret)
  652.  
downloadFlowNodesAIActionSequence.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top