BVB Source Codes

CRYENGINE Show FlowNodeAIAction.cpp Source code

Return Download CRYENGINE: download FlowNodeAIAction.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. /********************************************************************
  4.    -------------------------------------------------------------------------
  5.    File name:   FlowNodeAIAction.cpp
  6.    $Id$
  7.    Description: place for AI action related flow graph nodes
  8.  
  9.    -------------------------------------------------------------------------
  10.    History:
  11.    - 15:6:2005   15:24 : Created by Kirill Bulatsev
  12.  
  13.  *********************************************************************/
  14.  
  15. #include "StdAfx.h"
  16. #include <CryAISystem/IAISystem.h>
  17. #include <CryAISystem/IAgent.h>
  18. #include <CryAISystem/IAIActorProxy.h>
  19. #include "IActorSystem.h"
  20. #include "IVehicleSystem.h"
  21. #include "FlowNodeAIAction.h"
  22. #include <CryAISystem/IAIObject.h>
  23. #include <CryAISystem/IAIActor.h>
  24. #include <CryAISystem/IGoalPipe.h>
  25. #include "VehicleSystem/Vehicle.h"
  26. #include "VehicleSystem/VehicleSeat.h"
  27. #include <CryFlowGraph/IFlowBaseNode.h>
  28.  
  29. //#pragma optimize("", off)
  30. //#pragma inline_depth(0)
  31.  
  32. #define DEF_CLONE(CLASS) IFlowNodePtr CLASS::Clone(SActivationInfo * pActInfo){ CLASS* p = new CLASS(pActInfo); p->m_bNeedsExec = m_bNeedsExec; p->m_bNeedsSink = m_bNeedsSink; return p; }
  33.  
  34. static const char* RUN_SPEED_UICONFIG = "enum_int:VerySlow=0,Walk=1,Run=2,Sprint=3";
  35. static const char* STANCE_UICONFIG = "enum_int:Prone=0,Crouch=1,Combat=2,CombatAlerted=3,Relaxed=4,Stealth=5";
  36. static const char* FORCE_UICONFIG = "enum_int:No=0,KeepPerception=1,IgnoreAll=2";
  37. static const char* SECONDARY_UICONFIG = "enum_int:No=0,Any=1,Left=2,Right=3";
  38.  
  39. //////////////////////////////////////////////////////////////////////////
  40. // base AI Flow node
  41. //////////////////////////////////////////////////////////////////////////
  42. //
  43. //-------------------------------------------------------------------------------------------------------------
  44. template<bool TBlocking> CFlowNode_AIBase<TBlocking>::CFlowNode_AIBase(SActivationInfo* pActInfo)
  45.         : m_bExecuted(false)
  46.         , m_bSynchronized(false)
  47.         , m_bNeedsSink(false)
  48.         , m_bNeedsExec(false)
  49.         , m_bNeedsReset(true)
  50.         , m_EntityId(0)
  51.         , m_UnregisterEntityId(0)
  52.         , m_GoalPipeId(0)
  53.         , m_UnregisterGoalPipeId(0)
  54. {
  55.         //              m_entityId = (EntityId) pActInfo->m_pUserData;
  56.         m_nodeID = pActInfo->myID;
  57.         m_pGraph = pActInfo->pGraph;
  58. }
  59. //
  60. //-------------------------------------------------------------------------------------------------------------
  61. template<bool TBlocking> CFlowNode_AIBase<TBlocking>::~CFlowNode_AIBase()
  62. {
  63.         UnregisterEvents();
  64. }
  65.  
  66. //
  67. //-------------------------------------------------------------------------------------------------------------
  68. template<bool TBlocking> void CFlowNode_AIBase<TBlocking >::Serialize(SActivationInfo*, TSerialize ser)
  69. {
  70.         if (ser.IsReading())
  71.                 UnregisterEvents();
  72.  
  73.         ser.Value("GoalPipeId", m_GoalPipeId);
  74.         ser.Value("UnregisterGoalPipeId", m_UnregisterGoalPipeId);
  75.         ser.Value("EntityId", m_EntityId);
  76.         ser.Value("UnregisterEntityId", m_UnregisterEntityId);
  77.         ser.Value("bExecuted", m_bExecuted);
  78.         ser.Value("bSynchronized", m_bSynchronized);
  79.         ser.Value("bNeedsExec", m_bNeedsExec);
  80.         ser.Value("bNeedsSink", m_bNeedsSink);
  81.         ser.Value("bNeedsReset", m_bNeedsReset);
  82.  
  83.         if (ser.IsReading() && /*m_bBlocking &&*/ m_EntityId != 0)
  84.         {
  85.                 RegisterEntityEvents(); // We'll register for AI events in PostSerialize, once AI is created.
  86.         }
  87. }
  88.  
  89. //
  90. //-------------------------------------------------------------------------------------------------------------
  91. template<bool TBlocking> void CFlowNode_AIBase<TBlocking >::ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  92. {
  93.         if (event == eFE_ConnectInputPort)
  94.         {
  95.                 if (pActInfo->connectPort == 0)
  96.                         m_bNeedsExec = true;
  97.                 else if (pActInfo->connectPort == 1)
  98.                         m_bNeedsSink = true;
  99.         }
  100.         else if (event == eFE_DisconnectInputPort)
  101.         {
  102.                 if (pActInfo->connectPort == 0)
  103.                         m_bNeedsExec = false;
  104.                 else if (pActInfo->connectPort == 1)
  105.                         m_bNeedsSink = false;
  106.         }
  107.         else if (event == eFE_Initialize)
  108.         {
  109.                 if (m_bNeedsReset)
  110.                 {
  111.                         // it may happen that updates were enabled in previous game session
  112.                         pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, false);
  113.  
  114.                         UnregisterEvents();
  115.                         m_EntityId = 0;
  116.                         m_GoalPipeId = 0;
  117.                         m_bExecuted = false;
  118.                         m_bSynchronized = false;
  119.                         //              m_bNeedsExec = pActInfo->pEntity == 0;
  120.                         //              m_bNeedsSink = false;
  121.                         m_bNeedsReset = false;
  122.                 }
  123.                 if (m_bNeedsExec && pActInfo->pEntity && IsPortActive(pActInfo, -1))
  124.                 {
  125.                         // entity is dynamically assigned during initialization
  126.                         m_bNeedsExec = false;
  127.                 }
  128.         }
  129.         else if (event == eFE_SetEntityId && pActInfo->pGraph->GetAIAction() != NULL)
  130.         {
  131.                 m_bNeedsReset = true;
  132.                 if (m_bNeedsExec && !m_bExecuted && pActInfo->pEntity)
  133.                 {
  134.                         m_bNeedsReset = true;
  135.                         m_bExecuted = true;
  136.                         if (m_bSynchronized || !m_bNeedsSink)
  137.                                 pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, true);
  138.                 }
  139.         }
  140.         else if (event == eFE_SetEntityId && pActInfo->pGraph->GetAIAction() == NULL)
  141.         {
  142.                 m_bNeedsReset = true;
  143.                 if (m_bNeedsExec && !m_bExecuted && pActInfo->pEntity)
  144.                 {
  145.                         m_bNeedsReset = true;
  146.                         m_bExecuted = true;
  147.                         if (m_bSynchronized /*|| !m_bNeedsSink*/)
  148.                                 pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, true);
  149.                 }
  150.         }
  151.         else if (event == eFE_Activate)
  152.         {
  153.                 /*
  154.                     if ( IsPortActive(pActInfo, -1) )
  155.                     {
  156.                       m_bNeedsReset = true;
  157.                       if ( m_bNeedsExec && !m_bExecuted && pActInfo->pEntity )
  158.                       {
  159.                         m_bNeedsReset = true;
  160.                         m_bExecuted = true;
  161.                         if ( m_bSynchronized || !m_bNeedsSink )
  162.                           pActInfo->pGraph->SetRegularlyUpdated( pActInfo->myID, true );
  163.                       }
  164.                     }
  165.                  */
  166.                 if (IsPortActive(pActInfo, 0))
  167.                 {
  168.                         m_bNeedsReset = true;
  169.                         if (m_bNeedsSink && !m_bSynchronized)
  170.                         {
  171.                                 m_bSynchronized = true;
  172.                                 if (m_bExecuted || !m_bNeedsExec)
  173.                                         pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, true);
  174.                                 PreExecute(pActInfo);
  175.                         }
  176.                 }
  177.                 if (TBlocking && m_EntityId && m_GoalPipeId && IsPortActive(pActInfo, 1))
  178.                 {
  179.                         IEntity* pEntity = GetEntity(pActInfo);
  180.                         if (pEntity)
  181.                         {
  182.                                 IAIObject* pAI = pEntity->GetAI();
  183.                                 if (pAI)
  184.                                 {
  185.                                         IPipeUser* pPipeUser = pAI->CastToIPipeUser();
  186.                                         if (pPipeUser)
  187.                                                 OnCancelPortActivated(pPipeUser, pActInfo);
  188.                                 }
  189.                         }
  190.                 }
  191.         }
  192.         else if (event == eFE_Update)
  193.         {
  194.                 m_bNeedsReset = true;
  195.                 IEntity* pEntity = GetEntity(pActInfo);
  196.                 if (pEntity)
  197.                 {
  198.                         // first check is ai object updated at least once
  199.                         IAIObject* pAI = pEntity->GetAI();
  200.                         if (!pAI || !pAI->IsAgent() || pAI->IsUpdatedOnce())
  201.                         {
  202.                                 if (!OnUpdate(pActInfo))
  203.                                 {
  204.                                         pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, false);
  205.                                         TryExecute(pAI, event, pActInfo);
  206.  
  207.                                         m_bExecuted = false;
  208.                                         m_bSynchronized = false;
  209.                                 }
  210.                         }
  211.                         else
  212.                                 m_EntityId = 0;
  213.                 }
  214.                 else
  215.                 {
  216.                         pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, false);
  217.  
  218.                         m_bExecuted = false;
  219.                         m_bSynchronized = false;
  220.                 }
  221.         }
  222.         else if (event == eFE_Resume && m_EntityId)
  223.         {
  224.                 OnResume(pActInfo);
  225.                 //      UnregisterEvents();
  226.                 //      pActInfo->pGraph->SetRegularlyUpdated( pActInfo->myID, true );
  227.         }
  228. }
  229.  
  230. template<bool TBlocking>
  231. void CFlowNode_AIBase<TBlocking >::TryExecute(IAIObject* pAI, EFlowEvent event, SActivationInfo* pActInfo)
  232. {
  233.         // marcok: we use the CVar to control the check for alertness
  234.         static ICVar* aiFlowNodeAlertnessCheck = gEnv->pConsole->GetCVar("ai_FlowNodeAlertnessCheck");
  235.  
  236.         // check is the node inside an entity flow graph and alerted. if so fail execution
  237.         if (aiFlowNodeAlertnessCheck->GetIVal() && pAI && pAI->GetProxy() && pAI->GetProxy()->GetAlertnessState() && !pActInfo->pGraph->GetAIAction())
  238.         {
  239.                 IEntity* graphOwner = gEnv->pEntitySystem->GetEntity(pActInfo->pGraph->GetGraphEntity(0));
  240.                 AILogEventID("<Flowgraph> ", "Canceling execution of an AI flowgraph node because the agent '%s' alertness is too high (%d). Owner:%s Node:%d",
  241.                              pAI->GetName(), pAI->GetProxy()->GetAlertnessState(), graphOwner ? graphOwner->GetName() : "<unknown>", pActInfo->myID);
  242.  
  243.                 Cancel();
  244.         }
  245.         else
  246.                 DoProcessEvent(event, pActInfo);
  247. }
  248.  
  249. template<bool TBlocking> void CFlowNode_AIBase<TBlocking >::OnCancelPortActivated(IPipeUser* pPipeUser, SActivationInfo* pActInfo)
  250. {
  251.         if (m_GoalPipeId != -1)
  252.         {
  253.                 // We have a goal pipe for this flow node. Try to cancel it.
  254.                 if (pPipeUser->CancelSubPipe(m_GoalPipeId))
  255.                 {
  256.                         // We successfully canceled the sub pipe. This mean a deselect
  257.                         // event will be triggered and that will by itself call Cancel.
  258.                         return;
  259.                 }
  260.                 else
  261.                 {
  262.                         // We could not cancel the goal pipe. This might mean that
  263.                         // the pipe is not yet running, or it has already been canceled.
  264.                         // Fall through and call Cancel from here then.
  265.                 }
  266.         }
  267.  
  268.         Cancel();
  269. }
  270.  
  271. //
  272. //-------------------------------------------------------------------------------------------------------------
  273. template<bool TBlocking> void CFlowNode_AIBase<TBlocking >::OnGoalPipeEvent(IPipeUser* pPipeUser, EGoalPipeEvent event, int goalPipeId, bool& unregisterListenerAfterEvent)
  274. {
  275.         if (m_GoalPipeId != goalPipeId)
  276.                 return;
  277.  
  278.         switch (event)
  279.         {
  280.         case ePN_Deselected:
  281.                 Cancel();
  282.                 break;
  283.  
  284.         case ePN_Removed:
  285.         case ePN_Finished:
  286.                 Finish();
  287.                 break;
  288.  
  289.         case ePN_Suspended:
  290.                 break;
  291.  
  292.         case ePN_Resumed:
  293.         case ePN_RefPointMoved:
  294.                 OnResume();
  295.                 break;
  296.         }
  297. }
  298.  
  299. //
  300. //-------------------------------------------------------------------------------------------------------------
  301. template<bool TBlocking> void CFlowNode_AIBase<TBlocking >::OnEntityEvent(IEntity* pEntity, SEntityEvent& event)
  302. {
  303.         switch (event.event)
  304.         {
  305.         case ENTITY_EVENT_AI_DONE:
  306.                 if (m_pGraph->IsSuspended())
  307.                         return;
  308.                 Finish();
  309.                 break;
  310.  
  311.         case ENTITY_EVENT_RESET:
  312.         case ENTITY_EVENT_DONE:
  313.                 Cancel();
  314.                 break;
  315.  
  316.         case ENTITY_EVENT_POST_SERIALIZE:
  317.                 // AI are created after flowgraph is serialized, so RegisterEvents() needs to happen
  318.                 // on post serialize to make sure we register as goalpipe listeners.
  319.                 RegisterAIEvents();
  320.                 break;
  321.         }
  322. }
  323.  
  324. //
  325. //-------------------------------------------------------------------------------------------------------------
  326. template<bool TBlocking> void CFlowNode_AIBase<TBlocking >::Cancel()
  327. {
  328.         OnCancel();
  329.  
  330.         SFlowAddress done(m_nodeID, 0, true);
  331.         SFlowAddress fail(m_nodeID, 2, true);
  332.         m_pGraph->ActivatePort(done, m_EntityId);
  333.         m_pGraph->ActivatePort(fail, m_EntityId);
  334.  
  335.         if (m_EntityId)
  336.         {
  337.                 m_bExecuted = false;
  338.                 m_bSynchronized = false;
  339.  
  340.                 m_UnregisterEntityId = m_EntityId;
  341.                 m_EntityId = 0;
  342.  
  343.                 m_UnregisterGoalPipeId = m_GoalPipeId;
  344.                 m_GoalPipeId = 0;
  345.         }
  346. }
  347.  
  348. //
  349. //-------------------------------------------------------------------------------------------------------------
  350. template<bool TBlocking> void CFlowNode_AIBase<TBlocking >::Finish()
  351. {
  352.         OnFinish();
  353.  
  354.         SFlowAddress done(m_nodeID, 0, true);
  355.         SFlowAddress succeed(m_nodeID, 1, true);
  356.         m_pGraph->ActivatePort(done, m_EntityId);
  357.         m_pGraph->ActivatePort(succeed, m_EntityId);
  358.  
  359.         if (m_EntityId)
  360.         {
  361.                 m_bExecuted = false;
  362.                 m_bSynchronized = false;
  363.  
  364.                 m_UnregisterEntityId = m_EntityId;
  365.                 m_EntityId = 0;
  366.  
  367.                 m_UnregisterGoalPipeId = m_GoalPipeId;
  368.                 m_GoalPipeId = 0;
  369.         }
  370. }
  371.  
  372. //
  373. //-------------------------------------------------------------------------------------------------------------
  374. template<bool TBlocking> void CFlowNode_AIBase<TBlocking >::RegisterEvents()
  375. {
  376.         RegisterEntityEvents();
  377.         RegisterAIEvents();
  378. }
  379.  
  380. //
  381. //-------------------------------------------------------------------------------------------------------------
  382. template<bool TBlocking> void CFlowNode_AIBase<TBlocking >::RegisterEntityEvents()
  383. {
  384.         if (m_EntityId)
  385.         {
  386.                 IEntitySystem* pSystem = gEnv->pEntitySystem;
  387.                 pSystem->AddEntityEventListener(m_EntityId, ENTITY_EVENT_AI_DONE, this);
  388.                 pSystem->AddEntityEventListener(m_EntityId, ENTITY_EVENT_POST_SERIALIZE, this);
  389.                 //      pSystem->AddEntityEventListener( m_EntityId, ENTITY_EVENT_DONE, this );
  390.                 //      pSystem->AddEntityEventListener( m_EntityId, ENTITY_EVENT_RESET, this );
  391.         }
  392. }
  393.  
  394. //
  395. //-------------------------------------------------------------------------------------------------------------
  396. template<bool TBlocking> void CFlowNode_AIBase<TBlocking >::RegisterAIEvents()
  397. {
  398.         if (m_EntityId)
  399.         {
  400.                 if (m_GoalPipeId > 0)
  401.                 {
  402.                         IEntity* pEntity = gEnv->pEntitySystem->GetEntity(m_EntityId);
  403.                         if (pEntity)
  404.                         {
  405.                                 IAIObject* pAIObject = pEntity->GetAI();
  406.                                 if (pAIObject)
  407.                                 {
  408.                                         IPipeUser* pPipeUser = pAIObject->CastToIPipeUser();
  409.                                         if (pPipeUser)
  410.                                         {
  411.                                                 pPipeUser->RegisterGoalPipeListener(this, m_GoalPipeId, "CFlowNode_AIBase::RegisterEvents");
  412.                                         }
  413.                                 }
  414.                         }
  415.                 }
  416.         }
  417. }
  418.  
  419. //
  420. //-------------------------------------------------------------------------------------------------------------
  421. template<bool TBlocking> void CFlowNode_AIBase<TBlocking >::UnregisterEvents()
  422. {
  423.         if (m_UnregisterEntityId && !m_EntityId)
  424.                 m_EntityId = m_UnregisterEntityId;
  425.  
  426.         if (m_EntityId)
  427.         {
  428.                 IEntitySystem* pSystem = gEnv->pEntitySystem;
  429.                 if (pSystem)
  430.                 {
  431.                         pSystem->RemoveEntityEventListener(m_EntityId, ENTITY_EVENT_AI_DONE, this);
  432.                         pSystem->RemoveEntityEventListener(m_EntityId, ENTITY_EVENT_POST_SERIALIZE, this);
  433.                 }
  434.  
  435.                 if (m_UnregisterGoalPipeId && !m_GoalPipeId)
  436.                         m_GoalPipeId = m_UnregisterGoalPipeId;
  437.                 if (pSystem && m_GoalPipeId > 0)
  438.                 {
  439.                         IEntity* pEntity = pSystem->GetEntity(m_EntityId);
  440.                         if (pEntity)
  441.                         {
  442.                                 IAIObject* pAIObject = pEntity->GetAI();
  443.                                 if (pAIObject)
  444.                                 {
  445.                                         IPipeUser* pPipeUser = pAIObject->CastToIPipeUser();
  446.                                         if (pPipeUser)
  447.                                         {
  448.                                                 pPipeUser->UnRegisterGoalPipeListener(this, m_GoalPipeId);
  449.                                         }
  450.                                 }
  451.                         }
  452.                 }
  453.                 if (m_UnregisterGoalPipeId && m_GoalPipeId == m_UnregisterGoalPipeId)
  454.                         m_UnregisterGoalPipeId = 0;
  455.                 m_GoalPipeId = 0;
  456.  
  457.                 //      pSystem->RemoveEntityEventListener( m_EntityId, ENTITY_EVENT_DONE, this );
  458.                 //      pSystem->RemoveEntityEventListener( m_EntityId, ENTITY_EVENT_RESET, this );
  459.         }
  460.  
  461.         if (m_UnregisterEntityId && m_EntityId == m_UnregisterEntityId)
  462.                 m_UnregisterEntityId = 0;
  463.         m_EntityId = 0;
  464. }
  465.  
  466. //
  467. //-------------------------------------------------------------------------------------------------------------
  468. template<bool TBlocking> IEntity* CFlowNode_AIBase<TBlocking >::GetEntity(SActivationInfo* pActInfo)
  469. {
  470.         m_EntityId = 0;
  471.         if (pActInfo->pEntity)
  472.                 m_EntityId = pActInfo->pEntity->GetId();
  473.         return pActInfo->pEntity;
  474. }
  475.  
  476. //
  477. //-------------------------------------------------------------------------------------------------------------
  478. template<bool TBlocking> bool CFlowNode_AIBase<TBlocking >::Execute(SActivationInfo* pActInfo, const char* pSignalText, IAISignalExtraData* pData, int senderId)
  479. {
  480.         UnregisterEvents();
  481.  
  482.         IEntity* pEntity = GetEntity(pActInfo);
  483.         if (!pEntity)
  484.         {
  485.                 gEnv->pAISystem->FreeSignalExtraData(pData);
  486.  
  487.                 return false;
  488.         }
  489.  
  490.         IEntity* pSender = pEntity;
  491.         if (senderId)
  492.                 pSender = gEnv->pEntitySystem->GetEntity(senderId);
  493.  
  494.         bool result = false;
  495.         if (pEntity->HasAI())
  496.                 result = ExecuteOnAI(pActInfo, pSignalText, pData, pEntity, pSender);
  497.  
  498.         if (!result)
  499.                 result = ExecuteOnEntity(pActInfo, pSignalText, pData, pEntity, pSender);
  500.  
  501.         if (!result)
  502.         {
  503.                 gEnv->pAISystem->FreeSignalExtraData(pData);
  504.                 Cancel();
  505.         }
  506.  
  507.         return result;
  508. }
  509.  
  510. //
  511. //-------------------------------------------------------------------------------------------------------------
  512. template<bool TBlocking> bool CFlowNode_AIBase<TBlocking >::ExecuteOnAI(SActivationInfo* pActInfo, const char* pSignalText,
  513.                                                                         IAISignalExtraData* pData, IEntity* pEntity, IEntity* pSender)
  514. {
  515.         IAIObject* pAI = pEntity->GetAI();
  516.         CRY_ASSERT(pAI);
  517.         if (!pAI)
  518.                 return false;
  519.  
  520.         switch (pAI->GetAIType())
  521.         {
  522.         case AIOBJECT_VEHICLE:
  523.                 {
  524.                         // activate vehicle AI, unless it's destroyed
  525.                         IVehicle* pVehicle = gEnv->pGameFramework->GetIVehicleSystem()->GetVehicle(pEntity->GetId());
  526.                         if (!pVehicle || pVehicle->IsDestroyed())
  527.                                 return false;
  528.                         pAI->Event(AIEVENT_DRIVER_IN, NULL);  // enabling vehicle's full update to process signals, even if there is no driver
  529.                 }
  530.                 break;
  531.  
  532.         case AIOBJECT_ACTOR:
  533.                 break;
  534.  
  535.         case AIOBJECT_PLAYER:
  536.                 {
  537.                         // execute on player
  538.                         m_EntityId = pEntity->GetId();
  539.                         ActivateOutput(pActInfo, 0, m_EntityId);
  540.                         ActivateOutput(pActInfo, 1, m_EntityId);
  541.                         m_bExecuted = false;
  542.                         m_bSynchronized = false;
  543.                         m_EntityId = 0;
  544.                         m_GoalPipeId = -1;
  545.  
  546.                         IAIActor* pAIActor = pAI->CastToIAIActor();
  547.                         if (pAIActor)
  548.                                 pAIActor->SetSignal(10, pSignalText, pSender, pData);   // 10 means this signal must be sent (but sent[!], not set)
  549.                         else
  550.                                 gEnv->pAISystem->FreeSignalExtraData(pData);
  551.  
  552.                         // even if the same signal is already present in the queue
  553.                         return true;
  554.                 }
  555.         default:
  556.                 // invalid AIObject type
  557.                 return false;
  558.         }
  559.  
  560.         m_EntityId = pEntity->GetId();
  561.         m_GoalPipeId = gEnv->pAISystem->AllocGoalPipeId();
  562.  
  563.         if (m_bBlocking)
  564.         {
  565.                 RegisterEvents();
  566.  
  567.                 IAIActor* pAIActor = pAI->CastToIAIActor();
  568.                 if (pAIActor)
  569.                 {
  570.                         if (!pData)
  571.                                 pData = gEnv->pAISystem->CreateSignalExtraData();
  572.                         pData->iValue = m_GoalPipeId;
  573.                         pAIActor->SetSignal(10, pSignalText, pSender, pData);   // 10 means this signal must be sent (but sent[!], not set)
  574.                 }
  575.                 else
  576.                         gEnv->pAISystem->FreeSignalExtraData(pData);
  577.         }
  578.         else
  579.         {
  580.                 RegisterEvents();
  581.                 IAIActor* pAIActor = pAI->CastToIAIActor();
  582.                 if (pAIActor)
  583.                 {
  584.                         IAISignalExtraData* pExtraData = gEnv->pAISystem->CreateSignalExtraData();
  585.                         CRY_ASSERT(pExtraData);
  586.                         pExtraData->iValue = m_GoalPipeId;
  587.                         pAIActor->SetSignal(10, pSignalText, pSender, pData);   // 10 means this signal must be sent (but sent[!], not set)
  588.                         pAIActor->SetSignal(10, "ACT_DUMMY", pEntity, pExtraData);
  589.                 }
  590.                 else
  591.                         gEnv->pAISystem->FreeSignalExtraData(pData);
  592.         }
  593.  
  594.         return true;
  595. }
  596.  
  597. //
  598. //-------------------------------------------------------------------------------------------------------------
  599. template<bool TBlocking> bool CFlowNode_AIBase<TBlocking >::ExecuteOnEntity(SActivationInfo* pActInfo, const char* pSignalText,
  600.                                                                             IAISignalExtraData* pData, IEntity* pEntity, IEntity* pSender)
  601. {
  602.         // sorry, not implemented :(
  603.         //      CRY_ASSERT( 0 );
  604.         // dont assert: it's perfectly normal for this to happen at runtime for AISpawners
  605.         return false;
  606. }
  607.  
  608. // must sort-of match COPRunCmd::COPRunCmd
  609. template<bool TBlocking> void CFlowNode_AIBase<TBlocking >::SetSpeed(IAIObject* pAI, int iSpeed)
  610. {
  611.         IAIActor* pAIActor = pAI->CastToIAIActor();
  612.         if (!pAIActor)
  613.                 return;
  614.  
  615.         SOBJECTSTATE& state = pAIActor->GetState();
  616.  
  617.         // There is code/configuration elsewhere that means we won't even move at all if we select
  618.         // a "pseudo-speed" value that is too low (but still non-zero). So we're forced to hard-code these
  619.         // numbers in the hope that stuff elsewhere won't change because the interface makes us use a floating point number
  620.         // ("pseudoSpeed") to represent discrete states than a finite set of values.
  621.         if (iSpeed == -4)
  622.                 state.fMovementUrgency = -AISPEED_SPRINT;
  623.         if (iSpeed == -3)
  624.                 state.fMovementUrgency = -AISPEED_RUN;
  625.         if (iSpeed == -2)
  626.                 state.fMovementUrgency = -AISPEED_WALK;
  627.         if (iSpeed == -1)
  628.                 state.fMovementUrgency = -AISPEED_SLOW;
  629.         if (iSpeed == 0)
  630.                 state.fMovementUrgency = AISPEED_SLOW;
  631.         else if (iSpeed == 1)
  632.                 state.fMovementUrgency = AISPEED_WALK;
  633.         else if (iSpeed == 2)
  634.                 state.fMovementUrgency = AISPEED_RUN;
  635.         else if (iSpeed >= 3)
  636.                 state.fMovementUrgency = AISPEED_SPRINT;
  637. }
  638.  
  639. template<bool TBlocking> void CFlowNode_AIBase<TBlocking >::SetStance(IAIObject* pAI, int stance)
  640. {
  641.         IAIActor* pAIActor = pAI->CastToIAIActor();
  642.         if (!pAIActor)
  643.                 return;
  644.         SOBJECTSTATE& state = pAIActor->GetState();
  645.  
  646.         state.forceWeaponAlertness = false;
  647.  
  648.         switch (stance)
  649.         {
  650.         case 0:
  651.                 stance = STANCE_PRONE;
  652.                 break;
  653.         case 1:
  654.                 stance = STANCE_CROUCH;
  655.                 break;
  656.         case 2:
  657.                 stance = STANCE_STAND;
  658.                 break;
  659.         case 3:
  660.                 state.forceWeaponAlertness = true;
  661.                 stance = STANCE_ALERTED;
  662.                 break;
  663.         case 4:
  664.                 stance = STANCE_RELAXED;
  665.                 break;
  666.         case 5:
  667.                 stance = STANCE_STEALTH;
  668.                 break;
  669.         }
  670.  
  671.         state.bodystate = (EStance)stance;
  672.  
  673.         if (pAI->HasFormation())
  674.         {
  675.                 IAISignalExtraData* pData = gEnv->pAISystem->CreateSignalExtraData();
  676.                 pData->iValue = stance;
  677.                 gEnv->pAISystem->SendSignal(SIGNALFILTER_FORMATION_EXCEPT, 1, "OnChangeStance", pAI, pData);
  678.         }
  679. }
  680.  
  681. template<bool TBlocking> void CFlowNode_AIBase<TBlocking >::SetAllowStrafing(IAIObject* pAI, bool bAllowStrafing)
  682. {
  683.         IPipeUser* pPipeUser = pAI->CastToIPipeUser();
  684.         if (!pPipeUser)
  685.                 return;
  686.  
  687.         if (bAllowStrafing)
  688.                 pPipeUser->SetAllowedStrafeDistances(999999.0f, 999999.0f, true);
  689.         else
  690.                 pPipeUser->SetAllowedStrafeDistances(0, 0, false);
  691. }
  692.  
  693. template<bool TBlocking> void CFlowNode_AIForceableBase<TBlocking >::ProcessEvent(IFlowNode::EFlowEvent event, IFlowNode::SActivationInfo* pActInfo)
  694. {
  695.         if (event == IFlowNode::eFE_Initialize)
  696.         {
  697.                 if (this->m_bNeedsReset)
  698.                 {
  699.                         IEntity* pEntity = this->GetEntity(pActInfo);
  700.                         if (!pEntity)
  701.                                 return;
  702.  
  703.                         SetForceMethod(pEntity->GetAI(), eNoForce);
  704.                 }
  705.         }
  706.  
  707.         TBase::ProcessEvent(event, pActInfo);
  708. }
  709.  
  710. template<bool TBlocking> void CFlowNode_AIForceableBase<TBlocking >::TryExecute(IAIObject* pAI, IFlowNode::EFlowEvent event, IFlowNode::SActivationInfo* pActInfo)
  711. {
  712.         if (GetForceMethod(pActInfo) == eNoForce)
  713.                 TBase::TryExecute(pAI, event, pActInfo);  // Keep the old behavior
  714.         else
  715.                 this->DoProcessEvent(event, pActInfo);
  716. }
  717.  
  718. template<bool TBlocking> void CFlowNode_AIForceableBase<TBlocking >::SetForceMethod(IAIObject* pAI, EForceMethod method)
  719. {
  720.         if (!pAI)
  721.                 return;
  722.  
  723.         if (m_LastForceMethod == method)
  724.                 return;
  725.  
  726.         IAIActor* pAIActor = pAI->CastToIAIActor();
  727.         if (!pAIActor)
  728.                 return;
  729.  
  730.         if (m_LastForceMethod == eIgnoreAll)
  731.                 pAIActor->EnablePerception(true);
  732.  
  733.         IAIActorProxy* pAIProxy = pAIActor->GetProxy();
  734.  
  735.         switch (method)
  736.         {
  737.         case eIgnoreAll:
  738.                 pAIActor->ResetPerception();
  739.                 pAIActor->EnablePerception(false);
  740.         case eKeepPerception:
  741.                 if (pAIProxy)
  742.                         pAIProxy->SetForcedExecute(true);
  743.                 break;
  744.         case eNoForce:
  745.                 if (pAIProxy)
  746.                         pAIProxy->SetForcedExecute(false);
  747.                 break;
  748.         default:
  749.                 assert(0);
  750.                 break;
  751.         }
  752.  
  753.         m_LastForceMethod = method;
  754. }
  755.  
  756. template<bool TBlocking> void CFlowNode_AIForceableBase<TBlocking >::OnCancel()
  757. {
  758.         IEntity* pEntity = gEnv->pEntitySystem->GetEntity(this->m_EntityId);
  759.         if (!pEntity)
  760.                 return;
  761.  
  762.         SetForceMethod(pEntity->GetAI(), eNoForce);
  763. }
  764.  
  765. template<bool TBlocking> void CFlowNode_AIForceableBase<TBlocking >::OnFinish()
  766. {
  767.         IEntity* pEntity = gEnv->pEntitySystem->GetEntity(this->m_EntityId);
  768.         if (!pEntity)
  769.                 return;
  770.  
  771.         SetForceMethod(pEntity->GetAI(), eNoForce);
  772. }
  773.  
  774. template<bool TBlocking> void CFlowNode_AIForceableBase<TBlocking >::Serialize(IFlowNode::SActivationInfo* pActInfo, TSerialize ser)
  775. {
  776.         TBase::Serialize(pActInfo, ser);
  777.         int lastForceMethod = eNoForce;
  778.  
  779.         if (ser.IsWriting())
  780.         {
  781.                 lastForceMethod = (int) m_LastForceMethod;
  782.         }
  783.         ser.Value("m_LastForceMethod", lastForceMethod);
  784.         if (ser.IsReading())
  785.         {
  786.                 m_LastForceMethod = (EForceMethod)lastForceMethod;
  787.         }
  788. }
  789.  
  790. //---------------------------------------------------------------------------------------------------------------------------------
  791. //////////////////////////////////////////////////////////////////////////
  792. // generic AI order
  793. //////////////////////////////////////////////////////////////////////////
  794.  
  795. //
  796. //-------------------------------------------------------------------------------------------------------------
  797. template<class TDerivedFromSignalBase>
  798. void CFlowNode_AISignalBase<TDerivedFromSignalBase >::GetConfiguration(SFlowNodeConfig& config)
  799. {
  800.         static const SInputPortConfig in_config[] = {
  801.                 InputPortConfig_Void("sink", _HELP("for synchronization only"), _HELP("Sync")),
  802.                 { 0 }
  803.         };
  804.         config.sDescription = _HELP("Generic AI signal.");
  805.         config.pInputPorts = in_config;
  806.         config.pOutputPorts = 0;
  807.         config.nFlags |= EFLN_TARGET_ENTITY;
  808.         config.SetCategory(EFLN_APPROVED);
  809. }
  810.  
  811. //
  812. //-------------------------------------------------------------------------------------------------------------
  813. template<class TDerivedFromSignalBase>
  814. IFlowNodePtr CFlowNode_AISignalBase<TDerivedFromSignalBase >::Clone(SActivationInfo* pActInfo)
  815. {
  816.         //              pActInfo->m_pUserData = (void*) m_entityId;
  817.         TDerivedFromSignalBase* p = new TDerivedFromSignalBase(pActInfo);
  818.         p->m_bNeedsExec = m_bNeedsExec;
  819.         p->m_bNeedsSink = m_bNeedsSink;
  820.         return p;
  821. }
  822.  
  823. //
  824. //-------------------------------------------------------------------------------------------------------------
  825. template<class TDerivedFromSignalBase>
  826. void CFlowNode_AISignalBase<TDerivedFromSignalBase >::DoProcessEvent(IFlowNode::EFlowEvent event, IFlowNode::SActivationInfo* pActInfo)
  827. {
  828.         IEntity* pEntity = this->GetEntity(pActInfo);
  829.         if (!pEntity)
  830.                 return;
  831.         IAIObject* pAI = pEntity->GetAI();
  832.         if (!pAI)
  833.                 return;
  834.         IAIActor* pAIActor = pAI->CastToIAIActor();
  835.         if (!pAIActor)
  836.                 return;
  837.         unsigned short int nType = pAI->GetAIType();
  838.         if ((nType != AIOBJECT_ACTOR) && (nType != AIOBJECT_VEHICLE))
  839.                 return; // invalid AIObject type
  840.  
  841.         // not needed for now:
  842.         //if ( pAI->GetType() == AIOBJECT_VEHICLE )
  843.         //      pAI->Event( AIEVENT_ENABLE, NULL );
  844.  
  845.         IAISignalExtraData* pExtraData = GetExtraData(pActInfo);
  846.         pAIActor->SetSignal(10, m_SignalText, pEntity, pExtraData);
  847.  
  848.         // allow using the node more than once
  849.         this->m_bExecuted = false;
  850.         this->m_bSynchronized = false;
  851.         this->m_EntityId = 0;
  852. }
  853.  
  854. template<class TDerivedFromSignalBase>
  855. void CFlowNode_AISignalBase<TDerivedFromSignalBase >::TryExecute(IAIObject* pAI, EFlowEvent event, SActivationInfo* pActInfo)
  856. {
  857.         if (ShouldForce(pActInfo))
  858.                 DoProcessEvent(event, pActInfo);
  859.         else
  860.                 TBase::TryExecute(pAI, event, pActInfo);
  861. }
  862.  
  863. template<class TDerivedFromSignalBase>
  864. bool CFlowNode_AISignalBase<TDerivedFromSignalBase >::ShouldForce(IFlowNode::SActivationInfo* pActInfo) const
  865. {
  866.         return false;
  867. }
  868.  
  869. //
  870. //-------------------------------------------------------------------------------------------------------------
  871. template<class TDerivedFromSignalBase>
  872. void CFlowNode_AISignalBase<TDerivedFromSignalBase >::Cancel()
  873. {
  874.         // Note: This function is similar as the AIBase Cancel, but
  875.         // does not set the (Done/Succeed/Cancel) outputs since AISignalBase does not have them.
  876.         this->OnCancel();
  877.  
  878.         if (this->m_EntityId)
  879.         {
  880.                 this->m_bExecuted = false;
  881.                 this->m_bSynchronized = false;
  882.  
  883.                 this->m_UnregisterEntityId = this->m_EntityId;
  884.                 this->m_EntityId = 0;
  885.  
  886.                 this->m_UnregisterGoalPipeId = this->m_GoalPipeId;
  887.                 this->m_GoalPipeId = 0;
  888.         }
  889. }
  890.  
  891. //
  892. //-------------------------------------------------------------------------------------------------------------
  893. template<class TDerivedFromSignalBase>
  894. void CFlowNode_AISignalBase<TDerivedFromSignalBase >::Finish()
  895. {
  896.         // Note: This function is similar as the AIBase Finish, but
  897.         // does not set the (Done/Succeed/Cancel) outputs since AISignalBase does not have them.
  898.         this->OnFinish();
  899.  
  900.         if (this->m_EntityId)
  901.         {
  902.                 this->m_bExecuted = false;
  903.                 this->m_bSynchronized = false;
  904.  
  905.                 this->m_UnregisterEntityId = this->m_EntityId;
  906.                 this->m_EntityId = 0;
  907.  
  908.                 this->m_UnregisterGoalPipeId = this->m_GoalPipeId;
  909.                 this->m_GoalPipeId = 0;
  910.         }
  911. }
  912.  
  913. //////////////////////////////////////////////////////////////////////////
  914. // prototyping AI orders
  915. //////////////////////////////////////////////////////////////////////////
  916. //---------------------------------------------------------------------------------------------------------------------------------
  917. //////////////////////////////////////////////////////////////////////////
  918. // generic AI order
  919. //////////////////////////////////////////////////////////////////////////
  920.  
  921. //
  922. //-------------------------------------------------------------------------------------------------------------
  923. void CFlowNode_AISignal::GetConfiguration(SFlowNodeConfig& config)
  924. {
  925.         static const SInputPortConfig in_config[] = {
  926.                 InputPortConfig_Void("sink",       _HELP("for synchronization only"), _HELP("Sync")),
  927.                 InputPortConfig<string>("signal",  _HELP("order to execute")),
  928.                 InputPortConfig<Vec3>("posValue",  _HELP("pos signal data")),
  929.                 InputPortConfig<Vec3>("posValue2", _HELP("pos2 signal data")),
  930.                 InputPortConfig<int>("iValue",     _HELP("int signal data")),
  931.                 InputPortConfig<float>("fValue",   _HELP("float signal data")),
  932.                 InputPortConfig<string>("sValue",  _HELP("string signal data")),
  933.                 InputPortConfig<EntityId>("id",    _HELP("entity id signal data")),
  934.                 InputPortConfig<bool>("Force",     false,                             _HELP("send the signal even if alerted")),
  935.                 { 0 }
  936.         };
  937.         static const SOutputPortConfig out_config[] = {
  938.                 OutputPortConfig<EntityId>("done",    _HELP("action done")),
  939.                 OutputPortConfig<EntityId>("succeed", _HELP("action done successfully")),
  940.                 OutputPortConfig<EntityId>("fail",    _HELP("action failed")),
  941.                 { 0 }
  942.         };
  943.         config.sDescription = _HELP("Generic AI action.");
  944.         config.pInputPorts = in_config;
  945.         config.pOutputPorts = out_config;
  946.         config.nFlags |= EFLN_TARGET_ENTITY;
  947.         config.SetCategory(EFLN_APPROVED);
  948. }
  949.  
  950. bool CFlowNode_AISignal::ShouldForce(IFlowNode::SActivationInfo* pActInfo) const
  951. {
  952.         return GetPortBool(pActInfo, 8);
  953. }
  954.  
  955. DEF_CLONE(CFlowNode_AISignal)
  956.  
  957. //
  958. //-------------------------------------------------------------------------------------------------------------
  959. void CFlowNode_AISignal::DoProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  960. {
  961.         IAISignalExtraData* pData = gEnv->pAISystem->CreateSignalExtraData();
  962.         pData->point = GetPortVec3(pActInfo, 2);
  963.         pData->point2 = GetPortVec3(pActInfo, 3);
  964.         pData->iValue = GetPortInt(pActInfo, 4);
  965.         pData->fValue = GetPortFloat(pActInfo, 5);
  966.         pData->SetObjectName(GetPortString(pActInfo, 6));
  967.         pData->nID = GetPortEntityId(pActInfo, 7);
  968.  
  969.         Execute(pActInfo, GetPortString(pActInfo, 1), pData);
  970. }
  971.  
  972. void CFlowNode_AISignal::OnCancel()
  973. {
  974.         SFlowAddress done(m_nodeID, 0, true);
  975.         SFlowAddress fail(m_nodeID, 2, true);
  976.  
  977.         m_pGraph->ActivatePort(done, m_EntityId);
  978.         m_pGraph->ActivatePort(fail, m_EntityId);
  979. }
  980.  
  981. void CFlowNode_AISignal::OnFinish()
  982. {
  983.         SFlowAddress done(m_nodeID, 0, true);
  984.         SFlowAddress success(m_nodeID, 1, true);
  985.  
  986.         m_pGraph->ActivatePort(done, m_EntityId);
  987.         m_pGraph->ActivatePort(success, m_EntityId);
  988. }
  989.  
  990. //////////////////////////////////////////////////////////////////////////
  991. // Executes an Action
  992. //////////////////////////////////////////////////////////////////////////
  993.  
  994. //
  995. //-------------------------------------------------------------------------------------------------------------
  996. void CFlowNode_AIExecute::GetConfiguration(SFlowNodeConfig& config)
  997. {
  998.         static const SInputPortConfig in_config[] = {
  999.                 InputPortConfig_Void("sink",               _HELP("for synchronization only"),                                            _HELP("Sync")),
  1000.                 InputPortConfig_Void("cancel",             _HELP("cancels execution"),                                                   _HELP("Cancel")),
  1001.                 InputPortConfig<EntityId>("objectId",      _HELP("Entity ID of the object on which the agent should execute AI Action"), _HELP("ObjectId")),
  1002.                 InputPortConfig<string>("soaction_action", _HELP("AI action to be executed"),                                            _HELP("Action")),
  1003.                 InputPortConfig<int>("maxAlertness",       2,                                                                            _HELP("maximum alertness which allows execution (0, 1 or 2)"),                                      _HELP("MaxAlertness"),_UICONFIG("enum_int:Idle=0,Alerted=1,Combat=2")),
  1004.                 InputPortConfig<bool>("HighPriority",      true,                                                                         _HELP("action priority - use to force the action to be finished (except if alertness get higher)")),
  1005.                 InputPortConfig<int>("Force",              0,                                                                            _HELP("ForceExecution method"),                                                                     _HELP("Force"),  _UICONFIG(FORCE_UICONFIG)),
  1006.                 { 0 }
  1007.         };
  1008.         static const SOutputPortConfig out_config[] = {
  1009.                 OutputPortConfig<EntityId>("done",    _HELP("action done")),
  1010.                 OutputPortConfig<EntityId>("succeed", _HELP("action done successfully")),
  1011.                 OutputPortConfig<EntityId>("fail",    _HELP("action failed")),
  1012.                 { 0 }
  1013.         };
  1014.         config.sDescription = _HELP("Executes an AI Action");
  1015.         config.nFlags |= EFLN_TARGET_ENTITY;
  1016.         config.pInputPorts = in_config;
  1017.         config.pOutputPorts = out_config;
  1018.         config.SetCategory(EFLN_APPROVED);
  1019. }
  1020.  
  1021. DEF_CLONE(CFlowNode_AIExecute)
  1022.  
  1023. //
  1024. //-------------------------------------------------------------------------------------------------------------
  1025. CFlowNode_AIExecute::EForceMethod CFlowNode_AIExecute::GetForceMethod(IFlowNode::SActivationInfo* pActInfo) const
  1026. {
  1027.         return static_cast<EForceMethod>(GetPortInt(pActInfo, 6));
  1028. }
  1029.  
  1030. //
  1031. //-------------------------------------------------------------------------------------------------------------
  1032. void CFlowNode_AIExecute::DoProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  1033. {
  1034.         IEntity* pEntity = GetEntity(pActInfo);
  1035.         SetForceMethod(pEntity ? pEntity->GetAI() : 0, GetForceMethod(pActInfo));
  1036.  
  1037.         IAISignalExtraData* pData = gEnv->pAISystem->CreateSignalExtraData();
  1038.         pData->SetObjectName(GetPortString(pActInfo, 3));
  1039.         pData->nID = GetPortEntityId(pActInfo, 2);
  1040.         pData->fValue = (float)GetPortInt(pActInfo, 4);
  1041.  
  1042.         if (GetPortBool(pActInfo, 5))
  1043.                 pData->fValue += 100.0f;
  1044.  
  1045.         Execute(pActInfo, "ACT_EXECUTE", pData, GetPortEntityId(pActInfo, 2));
  1046. }
  1047.  
  1048. //
  1049. // should call DoProcessEvent if owner is not too much alerted
  1050. //-------------------------------------------------------------------------------------------------------------
  1051. void CFlowNode_AIExecute::TryExecute(IAIObject* pAI, EFlowEvent event, SActivationInfo* pActInfo)
  1052. {
  1053.         // check is the node inside an entity flow graph and alerted. if so fail execution
  1054.         if (pAI && pAI->GetProxy() && pAI->GetProxy()->GetAlertnessState() > GetPortInt(pActInfo, 4))
  1055.                 Cancel();
  1056.         else
  1057.                 DoProcessEvent(event, pActInfo);
  1058. }
  1059.  
  1060. //-------------------------------------------------------------------------------------------------------------
  1061. void CFlowNode_AIExecute::OnCancelPortActivated(IPipeUser* pPipeUser, SActivationInfo* pActInfo)
  1062. {
  1063.         if (m_EntityId)
  1064.         {
  1065.                 IEntity* pEntity = gEnv->pEntitySystem->GetEntity(m_EntityId);
  1066.                 if (pEntity && m_GoalPipeId > 0)
  1067.                 {
  1068.                         m_bCancel = true;
  1069.                         gEnv->pAISystem->GetAIActionManager()->AbortAIAction(pEntity, m_GoalPipeId);
  1070.                 }
  1071.         }
  1072. }
  1073.  
  1074. void CFlowNode_AIExecute::Cancel()
  1075. {
  1076.         m_bCancel = false;
  1077.         TBase::Cancel();
  1078. }
  1079.  
  1080. void CFlowNode_AIExecute::Finish()
  1081. {
  1082.         if (m_bCancel)
  1083.                 Cancel();
  1084.         else
  1085.                 TBase::Finish();
  1086. }
  1087.  
  1088. #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM
  1089. //////////////////////////////////////////////////////////////////////////
  1090. // Set Character
  1091. //////////////////////////////////////////////////////////////////////////
  1092.  
  1093. //
  1094. //-------------------------------------------------------------------------------------------------------------
  1095. void CFlowNode_AISetCharacter::GetConfiguration(SFlowNodeConfig& config)
  1096. {
  1097.         static const SInputPortConfig in_config[] = {
  1098.                 InputPortConfig_Void("sink",                      _HELP("for synchronization only"), _HELP("Sync")),
  1099.                 InputPortConfig<string>("aicharacter_character"),
  1100.                 { 0 }
  1101.         };
  1102.         static const SOutputPortConfig out_config[] = {
  1103.                 OutputPortConfig<EntityId>("done",    _HELP("action done")),
  1104.                 OutputPortConfig<EntityId>("succeed", _HELP("action done successfully")),
  1105.                 OutputPortConfig<EntityId>("fail",    _HELP("action failed")),
  1106.                 { 0 }
  1107.         };
  1108.         config.sDescription = _HELP("Changes AI Character");
  1109.         config.nFlags |= EFLN_TARGET_ENTITY;
  1110.         config.pInputPorts = in_config;
  1111.         config.pOutputPorts = out_config;
  1112.         config.SetCategory(EFLN_APPROVED);
  1113. }
  1114.  
  1115. DEF_CLONE(CFlowNode_AISetCharacter)
  1116.  
  1117. //
  1118. //-------------------------------------------------------------------------------------------------------------
  1119. void CFlowNode_AISetCharacter::DoProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  1120. {
  1121.         IEntity* pEntity = GetEntity(pActInfo);
  1122.         if (pEntity)
  1123.         {
  1124.                 bool success = false;
  1125.                 IAIObject* pAI = pEntity->GetAI();
  1126.                 if (pAI)
  1127.                 {
  1128.                         IPipeUser* pPipeUser = pAI->CastToIPipeUser();
  1129.                         if (pPipeUser)
  1130.                                 success = pPipeUser->SetCharacter(GetPortString(pActInfo, 1));
  1131.                 }
  1132.                 ActivateOutput(pActInfo, 0, m_EntityId);
  1133.                 ActivateOutput(pActInfo, success ? 1 : 2, m_EntityId);
  1134.                 m_bExecuted = false;
  1135.                 m_bSynchronized = false;
  1136.                 m_EntityId = 0;
  1137.         }
  1138. }
  1139. #endif
  1140.  
  1141. //////////////////////////////////////////////////////////////////////////
  1142. // Set State
  1143. //////////////////////////////////////////////////////////////////////////
  1144.  
  1145. //
  1146. //-------------------------------------------------------------------------------------------------------------
  1147. void CFlowNode_AISetState::GetConfiguration(SFlowNodeConfig& config)
  1148. {
  1149.         static const SInputPortConfig in_config[] = {
  1150.                 InputPortConfig_Void("sink",              _HELP("for synchronization only"), _HELP("Sync")),
  1151.                 InputPortConfig<string>("sostate_State"),
  1152.                 { 0 }
  1153.         };
  1154.         static const SOutputPortConfig out_config[] = {
  1155.                 OutputPortConfig<EntityId>("done",    _HELP("action done")),
  1156.                 OutputPortConfig<EntityId>("succeed", _HELP("action done successfully")),
  1157.                 OutputPortConfig<EntityId>("fail",    _HELP("action failed")),
  1158.                 { 0 }
  1159.         };
  1160.         config.sDescription = _HELP("Changes Smart Object State");
  1161.         config.nFlags |= EFLN_TARGET_ENTITY;
  1162.         config.pInputPorts = in_config;
  1163.         config.pOutputPorts = out_config;
  1164.         config.SetCategory(EFLN_ADVANCED);
  1165. }
  1166.  
  1167. DEF_CLONE(CFlowNode_AISetState)
  1168.  
  1169. //
  1170. //-------------------------------------------------------------------------------------------------------------
  1171. void CFlowNode_AISetState::DoProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  1172. {
  1173.         gEnv->pAISystem->GetSmartObjectManager()->SetSmartObjectState(GetEntity(pActInfo), GetPortString(pActInfo, 1));
  1174.         ActivateOutput(pActInfo, 0, m_EntityId);
  1175.         ActivateOutput(pActInfo, 1, m_EntityId);
  1176.         m_bExecuted = false;
  1177.         m_bSynchronized = false;
  1178.         m_EntityId = 0;
  1179. }
  1180.  
  1181. //////////////////////////////////////////////////////////////////////////
  1182. // Vehicle Follow Path
  1183. //////////////////////////////////////////////////////////////////////////
  1184.  
  1185. //
  1186. //-------------------------------------------------------------------------------------------------------------
  1187. void CFlowNode_AIVehicleFollowPath::GetConfiguration(SFlowNodeConfig& config)
  1188. {
  1189.         static const SInputPortConfig in_config[] = {
  1190.                 InputPortConfig_Void("sink",             _HELP("for synchronization only"),    _HELP("sync")),
  1191.                 InputPortConfig_Void("cancel",           _HELP("cancels execution")),
  1192.                 InputPortConfig<bool>("PathFindToStart", _HELP("Path-find to start of path")),
  1193.                 InputPortConfig<bool>("Reverse",         _HELP("Reverse the path direction")),
  1194.                 InputPortConfig<bool>("StartNearest",    false,                                _HELP("Starts the path at nearest point on path")),
  1195.                 InputPortConfig<int>("Loops",            0,                                    _HELP("Number of times to loop around the path (-1 = forever)")),
  1196.                 InputPortConfig<string>("path_name",     _HELP("Name of the path to follow"),  "Path Name"),
  1197.                 InputPortConfig<float>("Speed",          10,                                   _HELP("Speed"),                                                  _HELP("Speed (m/s)")),
  1198.                 InputPortConfig<int>("Force",            0,                                    _HELP("ForceExecution method"),                                  _HELP("Force"), _UICONFIG(FORCE_UICONFIG)),
  1199.                 { 0 }
  1200.         };
  1201.         static const SOutputPortConfig out_config[] = {
  1202.                 OutputPortConfig<EntityId>("done",    _HELP("action done")),
  1203.                 OutputPortConfig<EntityId>("succeed", _HELP("action done successfully")),
  1204.                 OutputPortConfig<EntityId>("fail",    _HELP("action failed")),
  1205.                 { 0 }
  1206.         };
  1207.         config.sDescription = _HELP("Follow path speed stance action");
  1208.         config.nFlags |= EFLN_TARGET_ENTITY;
  1209.         config.pInputPorts = in_config;
  1210.         config.pOutputPorts = out_config;
  1211.         config.SetCategory(EFLN_APPROVED);
  1212. }
  1213.  
  1214. DEF_CLONE(CFlowNode_AIVehicleFollowPath)
  1215.  
  1216. void CFlowNode_AIVehicleFollowPath::ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  1217. {
  1218.         // Dynamically update the point to approach to.
  1219.         if (m_EntityId && event == eFE_Activate && IsPortActive(pActInfo, 7))
  1220.         {
  1221.                 IEntity* pEntity = gEnv->pEntitySystem->GetEntity(m_EntityId);
  1222.                 if (pEntity)
  1223.                 {
  1224.                         if (IAIObject* pAI = pEntity->GetAI())
  1225.                         {
  1226.                                 unsigned short int nType = pAI->GetAIType();
  1227.                                 if (nType != AIOBJECT_VEHICLE)
  1228.                                 {
  1229.                                         CryWarning(VALIDATOR_MODULE_FLOWGRAPH, VALIDATOR_WARNING, "AI:VehicleFollowPath node should only be used to control vehicle entities");
  1230.                                         return;
  1231.                                 }
  1232.  
  1233.                                 IAIActor* pAIActor = pAI->CastToIAIActor();
  1234.                                 if (pAIActor)
  1235.                                 {
  1236.                                         pAIActor->GetState().fDesiredSpeed = GetPortFloat(pActInfo, 7);
  1237.                                 }
  1238.                         }
  1239.                 }
  1240.         }
  1241.         TBase::ProcessEvent(event, pActInfo);
  1242. }
  1243.  
  1244. //
  1245. //-------------------------------------------------------------------------------------------------------------
  1246. void CFlowNode_AIVehicleFollowPath::DoProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  1247. {
  1248.         bool pathFindToStart = GetPortBool(pActInfo, 2);
  1249.         bool reverse = GetPortBool(pActInfo, 3);
  1250.         bool nearest = GetPortBool(pActInfo, 4);
  1251.         int loops = GetPortInt(pActInfo, 5);
  1252.         const string& pathName = GetPortString(pActInfo, 6);
  1253.         float speed = GetPortFloat(pActInfo, 7);    // m/s, NOT the usual run/walk/sprint
  1254.  
  1255.         IEntity* pEntity = gEnv->pEntitySystem->GetEntity(m_EntityId);
  1256.         if (pEntity)
  1257.         {
  1258.                 if (IAIObject* pAI = pEntity->GetAI())
  1259.                 {
  1260.                         unsigned short int nType = pAI->GetAIType();
  1261.                         if (nType != AIOBJECT_VEHICLE)
  1262.                         {
  1263.                                 CryWarning(VALIDATOR_MODULE_FLOWGRAPH, VALIDATOR_WARNING, "AI:VehicleFollowPath node should only be used to control vehicle entities");
  1264.                                 return;
  1265.                         }
  1266.  
  1267.                         SetForceMethod(pAI, GetForceMethod(pActInfo));
  1268.  
  1269.                         pAI->CastToIAIActor()->SetPathToFollow(pathName.c_str());
  1270.  
  1271.                         IAISignalExtraData* pData = gEnv->pAISystem->CreateSignalExtraData();
  1272.                         pData->point2.x = (float)loops;
  1273.                         pData->fValue = (float)speed;
  1274.                         pData->point.x = pathFindToStart ? 1.0f : 0.0f;
  1275.                         pData->point.y = reverse ? 1.0f : 0.0f;
  1276.                         pData->point.z = nearest ? 1.0f : 0.0f;
  1277.                         pData->iValue2 = 1; // this means 'don't control speed'
  1278.                         Execute(pActInfo, "ACT_FOLLOWPATH", pData);
  1279.                 }
  1280.         }
  1281. }
  1282.  
  1283. CFlowNode_AIVehicleFollowPath::TBase::EForceMethod CFlowNode_AIVehicleFollowPath::GetForceMethod(SActivationInfo* pActInfo) const
  1284. {
  1285.         return static_cast<EForceMethod>(GetPortInt(pActInfo, 8));   // Replace this number with an enum value
  1286. }
  1287.  
  1288. //////////////////////////////////////////////////////////////////////////
  1289. // Vehicle Stick Path
  1290. //////////////////////////////////////////////////////////////////////////
  1291.  
  1292. //
  1293. //-------------------------------------------------------------------------------------------------------------
  1294. void CFlowNode_AIVehicleStickPath::GetConfiguration(SFlowNodeConfig& config)
  1295. {
  1296.         static const SInputPortConfig in_config[] = {
  1297.                 InputPortConfig_Void("sync",          _HELP("for synchronization only")),
  1298.                 InputPortConfig_Void("cancel",        _HELP("cancels execution")),
  1299.                 InputPortConfig<string>("path_name",  _HELP("Name of the path to stick to and follow"),                                                                                            "Path Name"),
  1300.                 InputPortConfig<bool>("Continuous",   false,                                                                                                                                       _HELP("Specifies if the vehicle should continue to follow the path (sticking to the target) or stop once it reaches the end or the specified target")),
  1301.                 InputPortConfig<bool>("CanReverse",   true,                                                                                                                                        _HELP("Specifies if the vehicle is allowed to drive in reverse to either follow its target or move along a looped path")),
  1302.                 InputPortConfig<float>("Speed",       10.0f,                                                                                                                                       _HELP("Speed"),                                                                                                                                         _HELP("Max speed of the vehicle (m/s)")),
  1303.                 InputPortConfig<float>("DistanceMin", 0.0f,                                                                                                                                        _HELP("Minimum stick distance to target"),                                                                                                              "Min Distance"),
  1304.                 InputPortConfig<float>("DistanceMax", 0.0f,                                                                                                                                        _HELP("Maximum stick distance to target"),                                                                                                              "Max Distance"),
  1305.                 InputPortConfig<EntityId>("Target",   _HELP("Id of the target to stick to when following the path. Non-continuous following means vehicle will stop once the target is reached.")),
  1306.                 InputPortConfig<int>("Force",         0,                                                                                                                                           _HELP("ForceExecution method"),                                                                                                                         _HELP("Force"),  _UICONFIG(FORCE_UICONFIG)),
  1307.                 { 0 }
  1308.         };
  1309.         static const SOutputPortConfig out_config[] = {
  1310.                 OutputPortConfig<EntityId>("done",    _HELP("action done")),
  1311.                 OutputPortConfig<EntityId>("succeed", _HELP("action done successfully")),
  1312.                 OutputPortConfig<EntityId>("fail",    _HELP("action failed")),
  1313.                 OutputPortConfig<EntityId>("close",   _HELP("close to destination")),
  1314.                 { 0 }
  1315.         };
  1316.         config.sDescription = _HELP("Follows the specified path to the end, sticking to the optional target, either continuously or as a one-off event. Use the vehicle with the node's Entity input.");
  1317.         config.nFlags |= EFLN_TARGET_ENTITY;
  1318.         config.pInputPorts = in_config;
  1319.         config.pOutputPorts = out_config;
  1320.         config.SetCategory(EFLN_APPROVED);
  1321. }
  1322.  
  1323. DEF_CLONE(CFlowNode_AIVehicleStickPath)
  1324.  
  1325. CFlowNode_AIVehicleStickPath::~CFlowNode_AIVehicleStickPath()
  1326. {
  1327.         UnregisterFromScriptEvent();
  1328. }
  1329.  
  1330. void CFlowNode_AIVehicleStickPath::Serialize(SActivationInfo* pActInfo, TSerialize ser)
  1331. {
  1332.         TBase::Serialize(pActInfo, ser);
  1333.  
  1334.         ser.Value("m_entityRegisteredToAsListener", m_entityRegisteredToAsListener);
  1335.         int val = m_outputToActivate;
  1336.         ser.Value("m_outputToActivate", val);
  1337.         m_outputToActivate = (Outputs)val;
  1338.         ser.Value("m_activateOutput", m_activateOutput);
  1339. }
  1340.  
  1341. void CFlowNode_AIVehicleStickPath::ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  1342. {
  1343.         switch (event)
  1344.         {
  1345.         case eFE_Initialize:
  1346.                 m_ID = pActInfo->myID;
  1347.                 TBase::ProcessEvent(event, pActInfo);
  1348.                 break;
  1349.         case eFE_Activate:
  1350.                 {
  1351.                         if (IsPortActive(pActInfo, 0))
  1352.                         {
  1353.                                 // Dynamically update the point to approach to.
  1354.                                 IEntity* pEntity = GetEntity(pActInfo);
  1355.  
  1356.                                 const string& pathName = GetPortString(pActInfo, 2);
  1357.                                 const bool bContinuous = GetPortBool(pActInfo, 3);
  1358.                                 const bool bCanReverse = GetPortBool(pActInfo, 4);
  1359.                                 const float speed = GetPortFloat(pActInfo, 5);    // m/s, NOT the usual run/walk/sprint
  1360.                                 const float distanceMin = GetPortFloat(pActInfo, 6);
  1361.                                 const float distanceMax = GetPortFloat(pActInfo, 7);
  1362.                                 const EntityId targetId = GetPortEntityId(pActInfo, 8);
  1363.  
  1364.                                 if (pEntity)
  1365.                                 {
  1366.                                         if (IAIObject* pAI = pEntity->GetAI())
  1367.                                         {
  1368.                                                 SetForceMethod(pAI, GetForceMethod(pActInfo));
  1369.  
  1370.                                                 IAIActor* pAIActor = pAI->CastToIAIActor();
  1371.                                                 if (pAIActor)
  1372.                                                 {
  1373.                                                         pAIActor->SetPathToFollow(pathName.c_str());
  1374.                                                         pAIActor->GetState().fDesiredSpeed = speed;
  1375.                                                 }
  1376.  
  1377.                                                 // ------------------------------------------------------------------
  1378.                                                 // make sure old sticpath nodes get cancelled
  1379.                                                 // ------------------------------------------------------------------
  1380.                                                 SEntityEvent cancelEvent(ENTITY_EVENT_SCRIPT_EVENT);
  1381.                                                 cancelEvent.nParam[0] = (INT_PTR)"PathCancelled";
  1382.                                                 cancelEvent.nParam[1] = IEntityClass::EVT_INT;
  1383.                                                 cancelEvent.nParam[2] = (INT_PTR)pActInfo->myID;
  1384.                                                 pEntity->SendEvent(cancelEvent);
  1385.                                                 // ------------------------------------------------------------------
  1386.  
  1387.                                                 IAISignalExtraData* pData = gEnv->pAISystem->CreateSignalExtraData();
  1388.                                                 pData->fValue = speed;
  1389.                                                 pData->iValue2 = (bContinuous ? 1 : 0);
  1390.                                                 pData->point.x = distanceMin;
  1391.                                                 pData->point.y = distanceMax;
  1392.                                                 pData->point.z = (bCanReverse ? 1.0f : 0.0f);
  1393.                                                 pData->nID.n = targetId;
  1394.                                                 Execute(pActInfo, "ACT_VEHICLESTICKPATH", pData);
  1395.  
  1396.                                                 pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, true);
  1397.                                                 RegisterForScriptEvent();
  1398.  
  1399.                                                 m_activateOutput = false;
  1400.                                         }
  1401.                                 }
  1402.                         }
  1403.                         else if (IsPortActive(pActInfo, 1))
  1404.                         {
  1405.                                 pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, false);
  1406.                                 UnregisterFromScriptEvent();
  1407.                         }
  1408.                         else if (IsPortActive(pActInfo, 5))
  1409.                         {
  1410.                                 // Dynamically update the point to approach to.
  1411.                                 IEntity* pEntity = GetEntity(pActInfo);
  1412.  
  1413.                                 if (pEntity)
  1414.                                 {
  1415.                                         if (IAIObject* pAI = pEntity->GetAI())
  1416.                                         {
  1417.                                                 IAIActor* pAIActor = pAI->CastToIAIActor();
  1418.  
  1419.                                                 if (IPipeUser* pipeUser = pAI->CastToIPipeUser())
  1420.                                                 {
  1421.                                                         IGoalPipe* pipe = pipeUser->GetCurrentGoalPipe();
  1422.  
  1423.                                                         if (pipe)
  1424.                                                         {
  1425.                                                                 pipe->ParseParam("desiredSpeed", GetPortFloat(pActInfo, 5));
  1426.                                                         }
  1427.                                                 }
  1428.  
  1429.                                                 if (pAIActor)
  1430.                                                 {
  1431.                                                         pAIActor->GetState().fDesiredSpeed = GetPortFloat(pActInfo, 5);
  1432.                                                 }
  1433.                                         }
  1434.                                 }
  1435.                         }
  1436.                 }
  1437.                 break;
  1438.  
  1439.         case eFE_Update:
  1440.                 if (m_activateOutput)
  1441.                 {
  1442.                         switch (m_outputToActivate)
  1443.                         {
  1444.                         case eOut_Failed:
  1445.                         case eOut_Succeeded:
  1446.                                 ActivateOutput(pActInfo, m_outputToActivate, m_EntityId);
  1447.                                 ActivateOutput(pActInfo, eOut_Done, m_EntityId);
  1448.                                 pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, false);
  1449.                                 break;
  1450.  
  1451.                         case eOut_Close:
  1452.                                 ActivateOutput(pActInfo, m_outputToActivate, m_EntityId);
  1453.                                 break;
  1454.  
  1455.                         default:
  1456.                                 ActivateOutput(pActInfo, m_outputToActivate, m_EntityId);
  1457.                                 pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, false);
  1458.                                 break;
  1459.                         }
  1460.  
  1461.                         m_activateOutput = false;
  1462.                 }
  1463.                 break;
  1464.  
  1465.         default:
  1466.                 TBase::ProcessEvent(event, pActInfo);
  1467.                 break;
  1468.         }
  1469. }
  1470.  
  1471. void CFlowNode_AIVehicleStickPath::RegisterForScriptEvent()
  1472. {
  1473.         UnregisterFromScriptEvent();
  1474.         m_entityRegisteredToAsListener = m_EntityId;
  1475.         gEnv->pEntitySystem->AddEntityEventListener(m_entityRegisteredToAsListener, ENTITY_EVENT_SCRIPT_EVENT, this);
  1476. }
  1477.  
  1478. void CFlowNode_AIVehicleStickPath::UnregisterFromScriptEvent()
  1479. {
  1480.         if (gEnv->pEntitySystem && m_entityRegisteredToAsListener)
  1481.         {
  1482.                 gEnv->pEntitySystem->RemoveEntityEventListener(m_entityRegisteredToAsListener, ENTITY_EVENT_SCRIPT_EVENT, this);
  1483.                 m_entityRegisteredToAsListener = 0;
  1484.         }
  1485. }
  1486.  
  1487. //
  1488. //-------------------------------------------------------------------------------------------------------------
  1489. void CFlowNode_AIVehicleStickPath::DoProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  1490. {
  1491.  
  1492. }
  1493.  
  1494. void CFlowNode_AIVehicleStickPath::PreExecute(SActivationInfo* pActInfo)
  1495. {
  1496. }
  1497.  
  1498. CFlowNode_AIVehicleStickPath::EForceMethod CFlowNode_AIVehicleStickPath::GetForceMethod(SActivationInfo* pActInfo) const
  1499. {
  1500.         return static_cast<EForceMethod>(GetPortInt(pActInfo, 9));   // Replace this number with an enum value
  1501. }
  1502.  
  1503. void CFlowNode_AIVehicleStickPath::OnEntityEvent(IEntity* pEntity, SEntityEvent& event)
  1504. {
  1505.         if (event.event == ENTITY_EVENT_SCRIPT_EVENT)
  1506.         {
  1507.                 const char* eventName = (const char*)event.nParam[0];
  1508.                 if (!strcmp("GoToSucceeded", eventName))
  1509.                 {
  1510.                         m_activateOutput = true;
  1511.                         m_outputToActivate = eOut_Succeeded;
  1512.                 }
  1513.                 else if (!strcmp("GoToFailed", eventName))
  1514.                 {
  1515.                         m_activateOutput = true;
  1516.                         m_outputToActivate = eOut_Failed;
  1517.                 }
  1518.                 else if (!strcmp("GoToCloseToDest", eventName))
  1519.                 {
  1520.                         m_activateOutput = true;
  1521.                         m_outputToActivate = eOut_Close;
  1522.                 }
  1523.                 else if (!strcmp("PathCancelled", eventName))
  1524.                 {
  1525.                         //only activate output if this event was not send by this instance
  1526.                         if (((event.nParam[1] == IEntityClass::EVT_INT) && event.nParam[2] != m_ID) ||
  1527.                             ((event.nParam[1] == IEntityClass::EVT_BOOL) && event.nParam[2] > 0))
  1528.                         {
  1529.                                 m_activateOutput = true;
  1530.                                 m_outputToActivate = eOut_Done;
  1531.                         }
  1532.                 }
  1533.  
  1534.                 if (m_activateOutput && (m_outputToActivate != eOut_Close))
  1535.                 {
  1536.                         gEnv->pEntitySystem->RemoveEntityEventListener(m_EntityId, ENTITY_EVENT_SCRIPT_EVENT, this);
  1537.                 }
  1538.         }
  1539. }
  1540.  
  1541. //////////////////////////////////////////////////////////////////////////
  1542. // Vehicle Chase Target
  1543. //////////////////////////////////////////////////////////////////////////
  1544.  
  1545. //
  1546. //-------------------------------------------------------------------------------------------------------------
  1547. void CFlowNode_AIVehicleChaseTarget::GetConfiguration(SFlowNodeConfig& config)
  1548. {
  1549.         static const SInputPortConfig in_config[] = {
  1550.                 InputPortConfig_Void("sync",          _HELP("for synchronization only")),
  1551.                 InputPortConfig_Void("cancel",        _HELP("cancels execution")),
  1552.                 InputPortConfig<string>("path_name",  _HELP("Name of the path to stick to and follow"),                                                                                            "Path Name"),
  1553.                 InputPortConfig<float>("Speed",       10.0f,                                                                                                                                       _HELP("Speed"),                            _HELP("Max speed of the vehicle (m/s)")),
  1554.                 InputPortConfig<float>("DistanceMin", 0.0f,                                                                                                                                        _HELP("Minimum chase distance to target"), "Min Distance"),
  1555.                 InputPortConfig<float>("DistanceMax", 0.0f,                                                                                                                                        _HELP("Maximum chase distance to target"), "Max Distance"),
  1556.                 InputPortConfig<EntityId>("Target",   _HELP("Id of the target to stick to when following the path. Non-continuous following means vehicle will stop once the target is reached.")),
  1557.                 InputPortConfig<int>("Force",         0,                                                                                                                                           _HELP("ForceExecution method"),            _HELP("Force"),  _UICONFIG(FORCE_UICONFIG)),
  1558.                 { 0 }
  1559.         };
  1560.         static const SOutputPortConfig out_config[] = {
  1561.                 OutputPortConfig<EntityId>("fail", _HELP("action failed")),
  1562.                 { 0 }
  1563.         };
  1564.         config.sDescription = _HELP("Follows/navigates on the specified path, trying to establish line of sight/fire with the specified target.");
  1565.         config.nFlags |= EFLN_TARGET_ENTITY;
  1566.         config.pInputPorts = in_config;
  1567.         config.pOutputPorts = out_config;
  1568.         config.SetCategory(EFLN_APPROVED);
  1569. }
  1570.  
  1571. DEF_CLONE(CFlowNode_AIVehicleChaseTarget)
  1572.  
  1573. void CFlowNode_AIVehicleChaseTarget::ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  1574. {
  1575.         switch (event)
  1576.         {
  1577.         case eFE_Initialize:
  1578.                 m_ID = pActInfo->myID;
  1579.                 TBase::ProcessEvent(event, pActInfo);
  1580.                 break;
  1581.         case eFE_Activate:
  1582.                 {
  1583.                         if (IsPortActive(pActInfo, 0))
  1584.                         {
  1585.                                 // Dynamically update the point to approach to.
  1586.                                 IEntity* pEntity = GetEntity(pActInfo);
  1587.  
  1588.                                 const string& pathName = GetPortString(pActInfo, 2);
  1589.                                 const float speed = GetPortFloat(pActInfo, 3);    // m/s, NOT the usual run/walk/sprint
  1590.                                 const float distanceMin = GetPortFloat(pActInfo, 4);
  1591.                                 const float distanceMax = GetPortFloat(pActInfo, 5);
  1592.                                 const EntityId targetId = GetPortEntityId(pActInfo, 6);
  1593.  
  1594.                                 if (pEntity)
  1595.                                 {
  1596.                                         if (IAIObject* pAI = pEntity->GetAI())
  1597.                                         {
  1598.                                                 SetForceMethod(pAI, GetForceMethod(pActInfo));
  1599.  
  1600.                                                 IAIActor* pAIActor = pAI->CastToIAIActor();
  1601.                                                 if (pAIActor)
  1602.                                                 {
  1603.                                                         pAIActor->SetPathToFollow(pathName.c_str());
  1604.                                                         pAIActor->GetState().fDesiredSpeed = speed;
  1605.                                                 }
  1606.  
  1607.                                                 // ------------------------------------------------------------------
  1608.                                                 // make sure old stickpath nodes get cancelled
  1609.                                                 // ------------------------------------------------------------------
  1610.                                                 SEntityEvent cancelEvent(ENTITY_EVENT_SCRIPT_EVENT);
  1611.                                                 cancelEvent.nParam[0] = (INT_PTR)"PathCancelled";
  1612.                                                 cancelEvent.nParam[1] = IEntityClass::EVT_INT;
  1613.                                                 cancelEvent.nParam[2] = (INT_PTR)pActInfo->myID;
  1614.                                                 pEntity->SendEvent(cancelEvent);
  1615.                                                 // ------------------------------------------------------------------
  1616.  
  1617.                                                 IAISignalExtraData* pData = gEnv->pAISystem->CreateSignalExtraData();
  1618.                                                 pData->fValue = speed;
  1619.                                                 pData->point.x = distanceMin;
  1620.                                                 pData->point.y = distanceMax;
  1621.                                                 pData->point.z = 0.0f;
  1622.                                                 pData->nID.n = targetId;
  1623.                                                 Execute(pActInfo, "ACT_CHASETARGET", pData);
  1624.  
  1625.                                                 pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, true);
  1626.                                                 //gEnv->pEntitySystem->AddEntityEventListener(m_EntityId, ENTITY_EVENT_SCRIPT_EVENT, this);
  1627.  
  1628.                                                 m_activateOutput = false;
  1629.                                         }
  1630.                                 }
  1631.                         }
  1632.                         else if (IsPortActive(pActInfo, 1))
  1633.                         {
  1634.                                 pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, false);
  1635.                                 //gEnv->pEntitySystem->RemoveEntityEventListener(m_EntityId, ENTITY_EVENT_SCRIPT_EVENT, this);
  1636.                         }
  1637.                         else if (IsPortActive(pActInfo, 5))
  1638.                         {
  1639.                                 // Dynamically update the point to approach to.
  1640.                                 IEntity* pEntity = GetEntity(pActInfo);
  1641.  
  1642.                                 if (pEntity)
  1643.                                 {
  1644.                                         if (IAIObject* pAI = pEntity->GetAI())
  1645.                                         {
  1646.                                                 IAIActor* pAIActor = pAI->CastToIAIActor();
  1647.  
  1648.                                                 if (IPipeUser* pipeUser = pAI->CastToIPipeUser())
  1649.                                                 {
  1650.                                                         if (IGoalPipe* pipe = pipeUser->GetCurrentGoalPipe())
  1651.                                                                 pipe->ParseParam("desiredSpeed", GetPortFloat(pActInfo, 3));
  1652.                                                 }
  1653.  
  1654.                                                 if (pAIActor)
  1655.                                                         pAIActor->GetState().fDesiredSpeed = GetPortFloat(pActInfo, 3);
  1656.                                         }
  1657.                                 }
  1658.                         }
  1659.                 }
  1660.                 break;
  1661.  
  1662.         case eFE_Update:
  1663.                 if (m_activateOutput)
  1664.                 {
  1665.                         ActivateOutput(pActInfo, m_outputToActivate, m_EntityId);
  1666.                         pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, false);
  1667.                         m_activateOutput = false;
  1668.                 }
  1669.                 break;
  1670.  
  1671.         default:
  1672.                 TBase::ProcessEvent(event, pActInfo);
  1673.                 break;
  1674.         }
  1675. }
  1676.  
  1677. //
  1678. //-------------------------------------------------------------------------------------------------------------
  1679. void CFlowNode_AIVehicleChaseTarget::DoProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  1680. {
  1681. }
  1682.  
  1683. void CFlowNode_AIVehicleChaseTarget::PreExecute(SActivationInfo* pActInfo)
  1684. {
  1685. }
  1686.  
  1687. CFlowNode_AIVehicleChaseTarget::EForceMethod CFlowNode_AIVehicleChaseTarget::GetForceMethod(SActivationInfo* pActInfo) const
  1688. {
  1689.         return static_cast<EForceMethod>(GetPortInt(pActInfo, 7));   // Replace this number with an enum value
  1690. }
  1691.  
  1692. void CFlowNode_AIVehicleChaseTarget::OnEntityEvent(IEntity* pEntity, SEntityEvent& event)
  1693. {
  1694.         if (event.event == ENTITY_EVENT_SCRIPT_EVENT)
  1695.         {
  1696.                 const char* eventName = (const char*)event.nParam[0];
  1697.                 if (!strcmp("PathCancelled", eventName))
  1698.                 {
  1699.                         //only activate output if this event was not send by this instance
  1700.                         if (((event.nParam[1] == IEntityClass::EVT_INT) && event.nParam[2] != m_ID) ||
  1701.                             ((event.nParam[1] == IEntityClass::EVT_BOOL) && event.nParam[2] > 0))
  1702.                         {
  1703.                                 m_activateOutput = true;
  1704.                         }
  1705.                 }
  1706.  
  1707.                 if (m_activateOutput)
  1708.                 {
  1709.                         gEnv->pEntitySystem->RemoveEntityEventListener(m_EntityId, ENTITY_EVENT_SCRIPT_EVENT, this);
  1710.                 }
  1711.         }
  1712. }
  1713.  
  1714. //////////////////////////////////////////////////////////////////////////
  1715. // Look At
  1716. //////////////////////////////////////////////////////////////////////////
  1717.  
  1718. //
  1719. //-------------------------------------------------------------------------------------------------------------
  1720. void CFlowNode_AILookAt::GetConfiguration(SFlowNodeConfig& config)
  1721. {
  1722.         static const SInputPortConfig in_config[] = {
  1723.                 InputPortConfig_Void("sink",          _HELP("for synchronization only"),          _HELP("Sync")),
  1724.                 InputPortConfig_Void("cancel",        _HELP("cancels execution")),
  1725.                 InputPortConfig<Vec3>("pos",          _HELP("point to look at"),                  _HELP("Point")),
  1726.                 InputPortConfig<Vec3>("Direction",    _HELP("direction to look at")),
  1727.                 InputPortConfig<EntityId>("objectId", _HELP("ID of the object to look at")),
  1728.                 InputPortConfig<float>("Duration",    _HELP("how long to look at [in seconds]")),
  1729.                 InputPortConfig<int>("Force",         0,                                          _HELP("ForceExecution method"),_HELP("Force"),_UICONFIG(FORCE_UICONFIG)),
  1730.                 { 0 }
  1731.         };
  1732.         static const SOutputPortConfig out_config[] = {
  1733.                 OutputPortConfig<EntityId>("done",    _HELP("action done")),
  1734.                 OutputPortConfig<EntityId>("succeed", _HELP("action done successfully")),
  1735.                 OutputPortConfig<EntityId>("fail",    _HELP("action failed")),
  1736.                 { 0 }
  1737.         };
  1738.         config.sDescription = _HELP("Sets AI to look at a point, entity or direction.");
  1739.         config.nFlags |= EFLN_TARGET_ENTITY | EFLN_AISEQUENCE_SUPPORTED;
  1740.         config.pInputPorts = in_config;
  1741.         config.pOutputPorts = out_config;
  1742.         config.SetCategory(EFLN_APPROVED);
  1743. }
  1744.  
  1745. DEF_CLONE(CFlowNode_AILookAt)
  1746.  
  1747. CFlowNode_AILookAt::EForceMethod CFlowNode_AILookAt::GetForceMethod(IFlowNode::SActivationInfo* pActInfo) const
  1748. {
  1749.         return static_cast<EForceMethod>(GetPortInt(pActInfo, 6));
  1750. }
  1751.  
  1752. //
  1753. //-------------------------------------------------------------------------------------------------------------
  1754. void CFlowNode_AILookAt::DoProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  1755. {
  1756.         IEntity* pEntity = GetEntity(pActInfo);
  1757.         if (!pEntity)
  1758.                 return;
  1759.  
  1760.         IAIObject* pAI = pEntity->GetAI();
  1761.         if (!pAI)
  1762.         {
  1763.                 Cancel();
  1764.                 return;
  1765.         }
  1766.  
  1767.         IAIActor* pAIActor = pAI->CastToIAIActor();
  1768.         if (!pAIActor)
  1769.         {
  1770.                 Cancel();
  1771.                 return;
  1772.         }
  1773.  
  1774.         Vec3 pos = GetPortVec3(pActInfo, 2);
  1775.         Vec3 dir = GetPortVec3(pActInfo, 3);
  1776.         EntityId objectEntityId = GetPortEntityId(pActInfo, 4);
  1777.  
  1778.         if (!pos.IsZero(0.001f) || !dir.IsZero(0.001f) || (objectEntityId != 0))
  1779.         {
  1780.                 // activate look at
  1781.                 m_startTime = 0.f;
  1782.                 m_bExecuted = true;
  1783.                 ClearLookTarget();
  1784.                 pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, true);
  1785.  
  1786.                 SetForceMethod(pAI, GetForceMethod(pActInfo));
  1787.         }
  1788.         else
  1789.         {
  1790.                 // reset look at
  1791.                 pAIActor->ResetLookAt();
  1792.  
  1793.                 Finish();
  1794.         }
  1795. }
  1796.  
  1797. bool CFlowNode_AILookAt::OnUpdate(SActivationInfo* pActInfo)
  1798. {
  1799.         if (!m_bExecuted)
  1800.                 return false;
  1801.  
  1802.         IEntity* pEntity = GetEntity(pActInfo);
  1803.         if (!pEntity)
  1804.                 return false;
  1805.  
  1806.         IAIObject* pAI = pEntity->GetAI();
  1807.         if (!pAI)
  1808.         {
  1809.                 Cancel();
  1810.                 return false;
  1811.         }
  1812.  
  1813.         IAIActor* pAIActor = pAI->CastToIAIActor();
  1814.         if (!pAIActor)
  1815.         {
  1816.                 Cancel();
  1817.                 return false;
  1818.         }
  1819.  
  1820.         // read inputs
  1821.         Vec3 pos = GetPortVec3(pActInfo, 2);
  1822.         if (pos.IsZero(0.001f))
  1823.         {
  1824.                 EntityId objectEntityId = GetPortEntityId(pActInfo, 4);
  1825.                 if (objectEntityId != 0)
  1826.                 {
  1827.                         if (IEntity* pObjectEntity = gEnv->pEntitySystem->GetEntity(objectEntityId))
  1828.                         {
  1829.                                 if (IAIObject* aiObject = pObjectEntity->GetAI())
  1830.                                 {
  1831.                                         pos = aiObject->GetPos();
  1832.                                 }
  1833.                                 else
  1834.                                 {
  1835.                                         pos = pObjectEntity->GetPos();
  1836.                                 }
  1837.                         }
  1838.                 }
  1839.         }
  1840.  
  1841.         Vec3 dir = GetPortVec3(pActInfo, 3);
  1842.         float duration = GetPortFloat(pActInfo, 5);
  1843.  
  1844.         // this is to enable canceling
  1845.         m_GoalPipeId = -1;
  1846.  
  1847.         if (!pos.IsZero(0.001f))
  1848.         {
  1849.                 // look at point
  1850.                 if (!m_startTime.GetValue())
  1851.                 {
  1852.                         SetLookTarget(pAI, pos);
  1853.  
  1854.                         if (pAIActor->SetLookAtPointPos(pos, true))
  1855.                         {
  1856.                                 if (duration > 0)
  1857.                                 {
  1858.                                         m_startTime = gEnv->pTimer->GetFrameStartTime() + duration;
  1859.                                 }
  1860.                                 else
  1861.                                 {
  1862.                                         m_bExecuted = false;
  1863.                                         pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, false);
  1864.                                         Finish();
  1865.                                 }
  1866.                         }
  1867.                 }
  1868.                 else
  1869.                 {
  1870.                         if (gEnv->pTimer->GetFrameStartTime() >= m_startTime)
  1871.                         {
  1872.                                 m_bExecuted = false;
  1873.                                 pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, false);
  1874.                                 pAIActor->ResetLookAt();
  1875.                                 Finish();
  1876.                         }
  1877.                         else
  1878.                         {
  1879.                                 SetLookTarget(pAI, pos);
  1880.                                 pAIActor->SetLookAtPointPos(pos, true);
  1881.                         }
  1882.                 }
  1883.         }
  1884.         else if (!dir.IsZero(0.001f))
  1885.         {
  1886.                 // look at direction
  1887.                 if (!m_startTime.GetValue())
  1888.                 {
  1889.                         if (pAIActor->SetLookAtDir(dir, true))
  1890.                         {
  1891.                                 if (duration > 0)
  1892.                                 {
  1893.                                         m_startTime = gEnv->pTimer->GetFrameStartTime() + duration;
  1894.                                 }
  1895.                                 else
  1896.                                 {
  1897.                                         m_bExecuted = false;
  1898.                                         pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, false);
  1899.                                         Finish();
  1900.                                 }
  1901.                         }
  1902.                 }
  1903.                 else
  1904.                 {
  1905.                         if (gEnv->pTimer->GetFrameStartTime() >= m_startTime)
  1906.                         {
  1907.                                 m_bExecuted = false;
  1908.                                 pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, false);
  1909.                                 pAIActor->ResetLookAt();
  1910.                                 Finish();
  1911.                         }
  1912.                 }
  1913.         }
  1914.         else
  1915.         {
  1916.                 // reset look at
  1917.                 m_bExecuted = false;
  1918.                 pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, false);
  1919.                 pAIActor->ResetLookAt();
  1920.                 Finish();
  1921.         }
  1922.  
  1923.         return true;
  1924. }
  1925.  
  1926. void CFlowNode_AILookAt::OnCancel()
  1927. {
  1928.         TBase::OnCancel();
  1929.  
  1930.         m_bExecuted = true;
  1931.         m_pGraph->SetRegularlyUpdated(m_nodeID, false);
  1932.  
  1933.         ClearLookTarget();
  1934.  
  1935.         IEntity* pEntity = gEnv->pEntitySystem->GetEntity(m_EntityId);
  1936.         if (pEntity)
  1937.         {
  1938.                 IAIObject* pAI = pEntity->GetAI();
  1939.                 if (pAI)
  1940.                 {
  1941.                         IAIActor* pAIActor = pAI->CastToIAIActor();
  1942.                         if (pAIActor)
  1943.                                 pAIActor->ResetLookAt();
  1944.                 }
  1945.         }
  1946. }
  1947.  
  1948. void CFlowNode_AILookAt::OnFinish()
  1949. {
  1950.         ClearLookTarget();
  1951. }
  1952.  
  1953. void CFlowNode_AILookAt::SetLookTarget(IAIObject* pAI, Vec3 pos)
  1954. {
  1955.         if (IPipeUser* pipeUser = pAI->CastToIPipeUser())
  1956.         {
  1957.                 if (!m_lookTarget.get())
  1958.                 {
  1959.                         m_lookTarget = pipeUser->CreateLookTarget();
  1960.                 }
  1961.  
  1962.                 *m_lookTarget = pos;
  1963.         }
  1964. }
  1965.  
  1966. void CFlowNode_AILookAt::ClearLookTarget()
  1967. {
  1968.         m_lookTarget.reset();
  1969. }
  1970.  
  1971. //////////////////////////////////////////////////////////////////////////
  1972. // body stance controller
  1973. //////////////////////////////////////////////////////////////////////////
  1974.  
  1975. //
  1976. //-------------------------------------------------------------------------------------------------------------
  1977. void CFlowNode_AIStance::GetConfiguration(SFlowNodeConfig& config)
  1978. {
  1979.         static const SInputPortConfig in_config[] = {
  1980.                 InputPortConfig_Void("sink",                                                                                                _HELP("for synchronization only"), _HELP("Sync")),
  1981.                 InputPortConfig<int>("stance",                                                                                              4,                                 _HELP("0-prone\n1-crouch\n2-combat\n3-combat alerted\n4-relaxed\n5-stealth"),
  1982.                                      _HELP("Stance"),                                                                                       _UICONFIG("enum_int:Prone=0,Crouch=1,Combat=2,CombatAlerted=3,Relaxed=4,Stealth=5")),
  1983.                 { 0 }
  1984.         };
  1985.         static const SOutputPortConfig out_config[] = {
  1986.                 OutputPortConfig<EntityId>("done",    _HELP("action done")),
  1987.                 OutputPortConfig<EntityId>("succeed", _HELP("action done successfully")),
  1988.                 OutputPortConfig<EntityId>("fail",    _HELP("action failed")),
  1989.                 { 0 }
  1990.         };
  1991.         config.sDescription = _HELP("Body stance controller.");
  1992.         config.pInputPorts = in_config;
  1993.         config.pOutputPorts = out_config;
  1994.         config.nFlags |= EFLN_TARGET_ENTITY | EFLN_AISEQUENCE_SUPPORTED;
  1995.         config.SetCategory(EFLN_APPROVED);
  1996. }
  1997.  
  1998. DEF_CLONE(CFlowNode_AIStance)
  1999.  
  2000. //
  2001. //-------------------------------------------------------------------------------------------------------------
  2002. void CFlowNode_AIStance::DoProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  2003. {
  2004.         IAIObject* pAI = GetEntity(pActInfo)->GetAI();
  2005.         IAIActor* pAIActor = CastToIAIActorSafe(pAI);
  2006.         if (!pAIActor)
  2007.         {
  2008.                 ActivateOutput(pActInfo, 0, m_EntityId);
  2009.                 ActivateOutput(pActInfo, 2, m_EntityId);
  2010.                 m_bExecuted = false;
  2011.                 m_bSynchronized = false;
  2012.                 m_EntityId = 0;
  2013.                 return;
  2014.         }
  2015.  
  2016.         bool success = true;
  2017.         SOBJECTSTATE& state = pAIActor->GetState();
  2018.  
  2019.         int stance = GetPortInt(pActInfo, 1);
  2020.         state.forceWeaponAlertness = false;
  2021.         switch (stance)
  2022.         {
  2023.         case 0:
  2024.                 stance = STANCE_PRONE;
  2025.                 break;
  2026.         case 1:
  2027.                 stance = STANCE_CROUCH;
  2028.                 break;
  2029.         case 2:
  2030.                 stance = STANCE_STAND;
  2031.                 break;
  2032.         case 3:
  2033.                 state.forceWeaponAlertness = true;
  2034.                 stance = STANCE_STAND;
  2035.                 break;
  2036.         case 4:
  2037.                 stance = STANCE_RELAXED;
  2038.                 break;
  2039.         case 5:
  2040.                 stance = STANCE_STEALTH;
  2041.                 break;
  2042.         default:
  2043.                 success = false;
  2044.                 break;
  2045.         }
  2046.         state.bodystate = stance;
  2047.  
  2048.         if (pAI->HasFormation())
  2049.         {
  2050.                 IAISignalExtraData* pData = gEnv->pAISystem->CreateSignalExtraData();
  2051.                 pData->iValue = stance;
  2052.                 gEnv->pAISystem->SendSignal(SIGNALFILTER_FORMATION_EXCEPT, 1, "OnChangeStance", pAI, pData);
  2053.         }
  2054.  
  2055.         ActivateOutput(pActInfo, 0, m_EntityId);
  2056.         ActivateOutput(pActInfo, success ? 1 : 2, m_EntityId);
  2057.         m_bExecuted = false;
  2058.         m_bSynchronized = false;
  2059.         m_EntityId = 0;
  2060. }
  2061.  
  2062. //////////////////////////////////////////////////////////////////////////
  2063. // unload vehicle
  2064. //////////////////////////////////////////////////////////////////////////
  2065.  
  2066. //
  2067. //-------------------------------------------------------------------------------------------------------------
  2068. void CFlowNode_AIUnload::GetConfiguration(SFlowNodeConfig& config)
  2069. {
  2070.         static const SInputPortConfig in_config[] = {
  2071.                 InputPortConfig_Void("sink",   _HELP("for synchronization only"), _HELP("Sync")),
  2072.                 InputPortConfig_Void("Cancel", _HELP("cancels execution")),
  2073.                 InputPortConfig<int>("Seat",   _HELP("seat(s) to be unloaded"),   NULL,          _UICONFIG("enum_int:All=0,AllExceptDriver=-1,AllExceptGunner=-2,Driver=1,Gunner=2,Seat03=3,Seat04=4,Seat05=5,Seat06=6,Seat07=7,Seat08=8,Seat09=9,Seat10=10,Seat11=11")),
  2074.                 { 0 }
  2075.         };
  2076.         static const SOutputPortConfig out_config[] = {
  2077.                 OutputPortConfig<EntityId>("done",    _HELP("action done")),
  2078.                 OutputPortConfig<EntityId>("succeed", _HELP("action done successfully")),
  2079.                 OutputPortConfig<EntityId>("fail",    _HELP("action failed")),
  2080.                 { 0 }
  2081.         };
  2082.         config.sDescription = _HELP("Unloads vehicle, ejecting specified passengers");
  2083.         config.pInputPorts = in_config;
  2084.         config.pOutputPorts = out_config;
  2085.         config.nFlags |= EFLN_TARGET_ENTITY;
  2086.         config.SetCategory(EFLN_APPROVED);
  2087. }
  2088.  
  2089. DEF_CLONE(CFlowNode_AIUnload)
  2090.  
  2091. //
  2092. //-------------------------------------------------------------------------------------------------------------
  2093. void CFlowNode_AIUnload::DoProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  2094. {
  2095.         CRY_ASSERT(0); // This function should not be called!
  2096. }
  2097.  
  2098. //
  2099. //-------------------------------------------------------------------------------------------------------------
  2100. void CFlowNode_AIUnload::ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  2101. {
  2102.         // Override processing of eFE_Update event
  2103.         if (event != eFE_Update)
  2104.         {
  2105.                 TBase::ProcessEvent(event, pActInfo);
  2106.         }
  2107.         else
  2108.         {
  2109.                 // regular updates are not needed anymore
  2110.                 pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, false);
  2111.  
  2112.                 m_bNeedsReset = true;
  2113.                 IEntity* pEntity = GetEntity(pActInfo);
  2114.                 if (pEntity)
  2115.                 {
  2116.                         // first check is the owner a vehicle
  2117.                         IAIObject* pAI = pEntity->GetAI();
  2118.                         IVehicle* pVehicle = gEnv->pGameFramework->GetIVehicleSystem()->GetVehicle(pEntity->GetId());
  2119.                         if (!pVehicle)
  2120.                         {
  2121.                                 m_EntityId = 0;
  2122.                                 gEnv->pLog->LogError("The owner entity '%s' of Vehicle:Unload FG node with ID %d is not a vehicle! ", pEntity->GetName(), pActInfo->myID);
  2123.                         }
  2124.                         else
  2125.                         {
  2126.                                 m_mapPassengers.clear();
  2127.                                 int seatsToUnload = GetPortInt(pActInfo, 2);
  2128.                                 int numSeats = pVehicle->GetSeatCount();
  2129.                                 switch (seatsToUnload)
  2130.                                 {
  2131.                                 case -2: // all except the gunner
  2132.                                         UnloadSeat(pVehicle, 1);
  2133.                                         for (int i = 3; i <= numSeats; ++i)
  2134.                                                 UnloadSeat(pVehicle, i);
  2135.                                         break;
  2136.                                 case -1: // all except the driver
  2137.                                         for (int i = 2; i <= numSeats; ++i)
  2138.                                                 UnloadSeat(pVehicle, i);
  2139.                                         break;
  2140.                                 case 0: // all
  2141.                                         for (int i = 1; i <= numSeats; ++i)
  2142.                                                 UnloadSeat(pVehicle, i);
  2143.                                         break;
  2144.                                 default:
  2145.                                         if (seatsToUnload <= numSeats)
  2146.                                         {
  2147.                                                 UnloadSeat(pVehicle, seatsToUnload);
  2148.                                         }
  2149.                                         else
  2150.                                         {
  2151.                                                 m_EntityId = 0;
  2152.                                                 gEnv->pLog->LogError("Invalid vehicle seat id on Vehicle:Unload FG node with ID %d! ", pActInfo->myID);
  2153.                                         }
  2154.                                 }
  2155.                                 m_numPassengers = m_mapPassengers.size();
  2156.                                 if (!m_numPassengers)
  2157.                                         Finish();
  2158.                         }
  2159.                 }
  2160.                 else
  2161.                 {
  2162.                         m_bExecuted = false;
  2163.                         m_bSynchronized = false;
  2164.                 }
  2165.         }
  2166. }
  2167.  
  2168. //
  2169. //-------------------------------------------------------------------------------------------------------------
  2170. void CFlowNode_AIUnload::UnloadSeat(IVehicle* pVehicle, int seatId)
  2171. {
  2172.         if (IVehicleSeat* pSeat = pVehicle->GetSeatById(seatId))
  2173.                 if (EntityId passengerId = pSeat->GetPassenger())
  2174.                         if (IEntity* pEntity = gEnv->pEntitySystem->GetEntity(passengerId))
  2175.                                 if (IAIObject* pAI = pEntity->GetAI())
  2176.                                         if (IAIActor* pAIActor = pAI->CastToIAIActor())
  2177.                                                 if (IPipeUser* pPipeUser = pAI->CastToIPipeUser())
  2178.                                                 {
  2179.                                                         int goalPipeId = gEnv->pAISystem->AllocGoalPipeId();
  2180.                                                         pPipeUser->RegisterGoalPipeListener(this, goalPipeId, "CFlowNode_AIUnload::UnloadSeat");
  2181.                                                         m_mapPassengers[goalPipeId] = passengerId;
  2182.  
  2183.                                                         IAISignalExtraData* pExtraData = gEnv->pAISystem->CreateSignalExtraData();
  2184.                                                         pExtraData->iValue = goalPipeId;
  2185.                                                         pAIActor->SetSignal(10, "ACT_EXITVEHICLE", pEntity, pExtraData);
  2186.                                                 }
  2187. }
  2188.  
  2189. //
  2190. //-------------------------------------------------------------------------------------------------------------
  2191. void CFlowNode_AIUnload::OnGoalPipeEvent(IPipeUser* pPipeUser, EGoalPipeEvent event, int goalPipeId, bool& unregisterListenerAfterEvent)
  2192. {
  2193.         std::map<int, EntityId>::iterator it = m_mapPassengers.find(goalPipeId);
  2194.         if (it == m_mapPassengers.end())
  2195.                 return;
  2196.  
  2197.         switch (event)
  2198.         {
  2199.         case ePN_Deselected:
  2200.         case ePN_Removed:
  2201.         case ePN_Finished:
  2202.                 if (--m_numPassengers == 0)
  2203.                         Finish();
  2204.                 break;
  2205.         case ePN_Suspended:
  2206.         case ePN_Resumed:
  2207.         case ePN_RefPointMoved:
  2208.                 break;
  2209.         }
  2210. }
  2211.  
  2212. //
  2213. //-------------------------------------------------------------------------------------------------------------
  2214. void CFlowNode_AIUnload::UnregisterEvents()
  2215. {
  2216.         std::map<int, EntityId>::iterator it, itEnd = m_mapPassengers.end();
  2217.         for (it = m_mapPassengers.begin(); it != itEnd; ++it)
  2218.         {
  2219.                 if (it->second && gEnv->pEntitySystem)
  2220.                 {
  2221.                         if (gEnv->pEntitySystem)
  2222.                                 if (IEntity* pEntity = gEnv->pEntitySystem->GetEntity(it->second))
  2223.                                         if (IAIObject* pAI = pEntity->GetAI())
  2224.                                                 if (IPipeUser* pPipeUser = pAI->CastToIPipeUser())
  2225.                                                         pPipeUser->UnRegisterGoalPipeListener(this, it->first);
  2226.                 }
  2227.         }
  2228.         m_mapPassengers.clear();
  2229.         TBase::UnregisterEvents();
  2230. }
  2231.  
  2232. //////////////////////////////////////////////////////////////////////////
  2233. // drop object
  2234. //////////////////////////////////////////////////////////////////////////
  2235.  
  2236. //
  2237. //-------------------------------------------------------------------------------------------------------------
  2238. void CFlowNode_AIDropObject::GetConfiguration(SFlowNodeConfig& config)
  2239. {
  2240.         static const SInputPortConfig in_config[] = {
  2241.                 InputPortConfig_Void("sink",     _HELP("for synchronization only"), _HELP("Sync")),
  2242.                 InputPortConfig_Void("cancel",   _HELP("cancels execution")),
  2243.                 InputPortConfig<Vec3>("impulse", _HELP("use for throwing")),
  2244.                 InputPortConfig<int>("Force",    0,                                 _HELP("ForceExecution method"),_HELP("Force"),_UICONFIG(FORCE_UICONFIG)),
  2245.                 { 0 }
  2246.         };
  2247.         static const SOutputPortConfig out_config[] = {
  2248.                 OutputPortConfig<EntityId>("done",    _HELP("action done")),
  2249.                 OutputPortConfig<EntityId>("succeed", _HELP("action done successfully")),
  2250.                 OutputPortConfig<EntityId>("fail",    _HELP("action failed")),
  2251.                 { 0 }
  2252.         };
  2253.         config.sDescription = _HELP("Drops grabbed object.");
  2254.         config.pInputPorts = in_config;
  2255.         config.pOutputPorts = out_config;
  2256.         config.nFlags |= EFLN_TARGET_ENTITY | EFLN_AISEQUENCE_SUPPORTED;
  2257.         config.SetCategory(EFLN_APPROVED);
  2258. }
  2259.  
  2260. DEF_CLONE(CFlowNode_AIDropObject)
  2261.  
  2262. //
  2263. //-------------------------------------------------------------------------------------------------------------
  2264. CFlowNode_AIDropObject::EForceMethod CFlowNode_AIDropObject::GetForceMethod(IFlowNode::SActivationInfo* pActInfo) const
  2265. {
  2266.         return static_cast<EForceMethod>(GetPortInt(pActInfo, 3));
  2267. }
  2268.  
  2269. //
  2270. //-------------------------------------------------------------------------------------------------------------
  2271. void CFlowNode_AIDropObject::DoProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  2272. {
  2273.         IEntity* pEntity = GetEntity(pActInfo);
  2274.         SetForceMethod(pEntity ? pEntity->GetAI() : 0, GetForceMethod(pActInfo));
  2275.  
  2276.         IAISignalExtraData* pData = gEnv->pAISystem->CreateSignalExtraData();
  2277.         pData->point = GetPortVec3(pActInfo, 2);
  2278.         Execute(pActInfo, "ACT_DROP_OBJECT", pData);
  2279. }
  2280.  
  2281. //////////////////////////////////////////////////////////////////////////
  2282. // Uses an object
  2283. //////////////////////////////////////////////////////////////////////////
  2284.  
  2285. //
  2286. //-------------------------------------------------------------------------------------------------------------
  2287. void CFlowNode_AIUseObject::GetConfiguration(SFlowNodeConfig& config)
  2288. {
  2289.         static const SInputPortConfig in_config[] = {
  2290.                 InputPortConfig_Void("sink",          _HELP("for synchronization only"),                            _HELP("Sync")),
  2291.                 InputPortConfig_Void("cancel",        _HELP("cancels execution")),
  2292.                 InputPortConfig<EntityId>("objectId", "Entity ID of the object which should be used by the agent"),
  2293.                 InputPortConfig<int>("Force",         0,                                                            _HELP("ForceExecution method"),_HELP("Force"),_UICONFIG(FORCE_UICONFIG)),
  2294.                 { 0 }
  2295.         };
  2296.         static const SOutputPortConfig out_config[] = {
  2297.                 OutputPortConfig<EntityId>("done",    _HELP("action done")),
  2298.                 OutputPortConfig<EntityId>("succeed", _HELP("action done successfully")),
  2299.                 OutputPortConfig<EntityId>("fail",    _HELP("action failed")),
  2300.                 { 0 }
  2301.         };
  2302.         config.sDescription = _HELP("Uses an object");
  2303.         config.nFlags |= EFLN_TARGET_ENTITY;
  2304.         config.pInputPorts = in_config;
  2305.         config.pOutputPorts = out_config;
  2306.         config.SetCategory(EFLN_APPROVED);
  2307. }
  2308.  
  2309. DEF_CLONE(CFlowNode_AIUseObject)
  2310.  
  2311. //
  2312. //-------------------------------------------------------------------------------------------------------------
  2313. CFlowNode_AIUseObject::EForceMethod CFlowNode_AIUseObject::GetForceMethod(IFlowNode::SActivationInfo* pActInfo) const
  2314. {
  2315.         return static_cast<EForceMethod>(GetPortInt(pActInfo, 3));
  2316. }
  2317.  
  2318. //
  2319. //-------------------------------------------------------------------------------------------------------------
  2320. void CFlowNode_AIUseObject::DoProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  2321. {
  2322.         IEntity* pEntity = GetEntity(pActInfo);
  2323.         SetForceMethod(pEntity ? pEntity->GetAI() : 0, GetForceMethod(pActInfo));
  2324.  
  2325.         Execute(pActInfo, "ACT_USEOBJECT", NULL, GetPortEntityId(pActInfo, 2));
  2326. }
  2327.  
  2328. //////////////////////////////////////////////////////////////////////////
  2329. // Makes ai enter specified seat of specified vehicle
  2330. //////////////////////////////////////////////////////////////////////////
  2331. void CFlowNode_AIEnterVehicle::GetConfiguration(SFlowNodeConfig& config)
  2332. {
  2333.         static const SInputPortConfig in_config[] = {
  2334.                 InputPortConfig_Void("Trigger",        _HELP("for synchronization only")),
  2335.                 InputPortConfig_Void("Cancel",         _HELP("Cancels execution")),
  2336.                 InputPortConfig<EntityId>("VehicleId", _HELP("Vehicle to be entered")),
  2337.                 InputPortConfig<string>("SeatNumber",  _HELP("Seat to be entered"),                              _HELP("Seat"),                   _UICONFIG("dt=vehicleSeats, ref_entity=VehicleId")),
  2338.                 InputPortConfig<bool>("Fast",          _HELP("Skip approaching and playing entering animation")),
  2339.                 InputPortConfig<int>("Force",          eNoForce,                                                 _HELP("ForceExecution method"),  _HELP("Force"),                                     _UICONFIG(FORCE_UICONFIG)),
  2340.                 { 0 }
  2341.         };
  2342.         static const SOutputPortConfig out_config[] = {
  2343.                 OutputPortConfig<EntityId>("Done",    _HELP("Activated when the action finished")),
  2344.                 OutputPortConfig<EntityId>("Success", _HELP("Activated when Vehicle:Enter action succeeded")),
  2345.                 OutputPortConfig<EntityId>("Fail",    _HELP("Activated when Vehicle:Enter action failed")),
  2346.                 { 0 }
  2347.         };
  2348.  
  2349.         config.sDescription = _HELP("Makes AI enter specified seat of specified vehicle");
  2350.         config.nFlags |= EFLN_TARGET_ENTITY;
  2351.         config.pInputPorts = in_config;
  2352.         config.pOutputPorts = out_config;
  2353.         config.SetCategory(EFLN_APPROVED);
  2354. }
  2355.  
  2356. DEF_CLONE(CFlowNode_AIEnterVehicle)
  2357.  
  2358. //
  2359. //-------------------------------------------------------------------------------------------------------------
  2360. CFlowNode_AIEnterVehicle::EForceMethod CFlowNode_AIEnterVehicle::GetForceMethod(IFlowNode::SActivationInfo* pActInfo) const
  2361. {
  2362.         return static_cast<EForceMethod>(GetPortInt(pActInfo, eIn_ForceMethod));
  2363. }
  2364.  
  2365. //
  2366. //-------------------------------------------------------------------------------------------------------------
  2367. void CFlowNode_AIEnterVehicle::DoProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  2368. {
  2369.         if (!pActInfo->pEntity)
  2370.         {
  2371.                 ActivateOutput(pActInfo, eOut_Fail, INVALID_ENTITYID);
  2372.                 return;
  2373.         }
  2374.  
  2375.         bool bFast = GetPortBool(pActInfo, eIn_Fast);
  2376.         bool bSuccess = false;
  2377.  
  2378.         // test that we can enter the vehicle
  2379.         EntityId vehicleId = GetPortEntityId(pActInfo, eIn_VehicleId);
  2380.         IVehicle* pVehicle = CCryAction::GetCryAction()->GetIVehicleSystem()->GetVehicle(vehicleId);
  2381.         if (!pVehicle || pVehicle->IsCrewHostile(pActInfo->pEntity->GetId()))
  2382.         {
  2383.                 CryLog("Actor %s failed to enter vehicle (IsCrewHostile returned true)", pActInfo->pEntity->GetName());
  2384.                 ActivateOutput(pActInfo, eOut_Fail, pActInfo->pEntity->GetId());
  2385.                 return;
  2386.         }
  2387.  
  2388.         TVehicleSeatId seatId = pVehicle->GetSeatId(GetPortString(pActInfo, eIn_Seat));
  2389.  
  2390.         if (!bFast)
  2391.         {
  2392.                 ICVar* pTransitionsVar = gEnv->pConsole->GetCVar("v_transitionAnimations");
  2393.                 if (pTransitionsVar && pTransitionsVar->GetIVal() == 0)
  2394.                         bFast = true;
  2395.         }
  2396.  
  2397.         IEntity* pEntity = GetEntity(pActInfo);
  2398.  
  2399.         SetForceMethod(pEntity ? pEntity->GetAI() : 0, GetForceMethod(pActInfo));
  2400.  
  2401.         IActor* pActor = pEntity ? CCryAction::GetCryAction()->GetIActorSystem()->GetActor(pEntity->GetId()) : 0;
  2402.  
  2403.         if (pActor && pActor->IsPlayer())
  2404.         {
  2405.                 if (IVehicleSeat* pVehicleSeat = pVehicle->GetSeatById(seatId))
  2406.                 {
  2407.                         bSuccess = pVehicleSeat->Enter(pEntity->GetId(), true);
  2408.                 }
  2409.         }
  2410.         else if (pEntity && pEntity->GetAI())
  2411.         {
  2412.                 IAISignalExtraData* pData = gEnv->pAISystem->CreateSignalExtraData();
  2413.  
  2414.                 pData->fValue = (float)seatId;
  2415.                 pData->nID = vehicleId;
  2416.                 pData->iValue2 = bFast;
  2417.  
  2418.                 bSuccess = Execute(pActInfo, "ACT_ENTERVEHICLE", pData);
  2419.         }
  2420.         else if (pActor)
  2421.         {
  2422.                 IVehicleSeat* seat = pVehicle->GetSeatById(seatId);
  2423.                 if (seat)
  2424.                 {
  2425.                         pActor->HolsterItem(true);
  2426.                         pActor->MountedGunControllerEnabled(false);
  2427.                         pActor->GetGameObject()->SetAspectProfile(eEA_Physics, eAP_Alive);
  2428.                         bSuccess = seat->Enter(pEntity->GetId(), true);
  2429.                 }
  2430.         }
  2431.  
  2432.         // PS - Allow node to fire a second time.
  2433.         m_bNeedsExec = false;
  2434.         ActivateOutput(pActInfo, eOut_Success, pEntity->GetId());
  2435. }
  2436.  
  2437. //////////////////////////////////////////////////////////////////////////
  2438. // Get vehicle seat helper positions
  2439. //////////////////////////////////////////////////////////////////////////
  2440. void CFlowNode_GetSeatHelperVehicle::GetConfiguration(SFlowNodeConfig& config)
  2441. {
  2442.         static const SInputPortConfig in_config[] = {
  2443.                 InputPortConfig_Void("Get",           _HELP("Trigger to get the values"),                    _HELP("Trigger")),
  2444.                 InputPortConfig<string>("SeatNumber", _HELP("Seat that is connected to the 'enter' helper"), _HELP("Seat"),    _UICONFIG("dt=vehicleSeats, ref_entity=entityId")),
  2445.                 { 0 }
  2446.         };
  2447.         static const SOutputPortConfig out_config[] = {
  2448.                 OutputPortConfig<Vec3>("pos", _HELP("Position of the seat helper")),
  2449.                 OutputPortConfig<Vec3>("dir", _HELP("Direction of the seat helper")),
  2450.                 { 0 }
  2451.         };
  2452.  
  2453.         config.sDescription = _HELP("Gets the position and orientation of a seat's 'enter' helper in world space");
  2454.         config.nFlags |= EFLN_TARGET_ENTITY;
  2455.         config.pInputPorts = in_config;
  2456.         config.pOutputPorts = out_config;
  2457.         config.SetCategory(EFLN_APPROVED);
  2458. }
  2459.  
  2460. //
  2461. //-------------------------------------------------------------------------------------------------------------
  2462. void CFlowNode_GetSeatHelperVehicle::ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  2463. {
  2464.         CFlowVehicleBase::ProcessEvent(event, pActInfo); // handles eFE_SetEntityId
  2465.  
  2466.         if (event == eFE_Activate && IsPortActive(pActInfo, eIn_Get))
  2467.         {
  2468.                 CVehicle* pVehicle = static_cast<CVehicle*>(GetVehicle());
  2469.                 if (pVehicle)
  2470.                 {
  2471.                         const string seatName = GetPortString(pActInfo, eIn_Seat);
  2472.                         CVehicleSeat* pSeat = static_cast<CVehicleSeat*>(pVehicle->GetSeatById(pVehicle->GetSeatId(seatName)));
  2473.                         if (pSeat)
  2474.                         {
  2475.                                 Matrix34 tm;
  2476.                                 pSeat->GetEnterHelper()->GetWorldTM(tm);
  2477.                                 ActivateOutput(pActInfo, eOut_Pos, tm.GetTranslation());
  2478.                                 ActivateOutput(pActInfo, eOut_Dir, tm.GetColumn(1));
  2479.                         }
  2480.                 }
  2481.         }
  2482. }
  2483.  
  2484. //-------------------------------------------------------------------------------------------------------------
  2485. //
  2486. //-------------------------------------------------------------------------------------------------------------
  2487.  
  2488. REGISTER_FLOW_NODE("AI:Execute", CFlowNode_AIExecute)
  2489. REGISTER_FLOW_NODE("AI:Signal", CFlowNode_AISignal)
  2490. REGISTER_FLOW_NODE("AI:SetState", CFlowNode_AISetState)
  2491. REGISTER_FLOW_NODE("AI:LookAt", CFlowNode_AILookAt)
  2492. REGISTER_FLOW_NODE("AI:Stance", CFlowNode_AIStance)
  2493. #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM
  2494. REGISTER_FLOW_NODE("AI:CharacterSet", CFlowNode_AISetCharacter)
  2495. #endif
  2496. REGISTER_FLOW_NODE("AI:ObjectDrop", CFlowNode_AIDropObject)
  2497. REGISTER_FLOW_NODE("AI:ObjectUse", CFlowNode_AIUseObject)
  2498. REGISTER_FLOW_NODE("AI:AlertMe", CFlowNode_AISignalAlerted)
  2499. REGISTER_FLOW_NODE("Vehicle:Enter", CFlowNode_AIEnterVehicle)
  2500. REGISTER_FLOW_NODE("Vehicle:Unload", CFlowNode_AIUnload)
  2501. REGISTER_FLOW_NODE("Vehicle:FollowPath", CFlowNode_AIVehicleFollowPath)
  2502. REGISTER_FLOW_NODE("Vehicle:StickPath", CFlowNode_AIVehicleStickPath)
  2503. REGISTER_FLOW_NODE("Vehicle:ChaseTarget", CFlowNode_AIVehicleChaseTarget)
  2504. REGISTER_FLOW_NODE("Vehicle:GetSeatHelper", CFlowNode_GetSeatHelperVehicle)
  2505.  
  2506. #undef DEF_CLONE
  2507.  
downloadFlowNodeAIAction.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