BVB Source Codes

CRYENGINE Show AIHandler.cpp Source code

Return Download CRYENGINE: download AIHandler.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. /********************************************************************
  4.    CryGame Source File.
  5.    -------------------------------------------------------------------------
  6.    File name:   AIHandler.cpp
  7.    Version:     v1.00
  8.    Description:
  9.  
  10.    -------------------------------------------------------------------------
  11.    History:
  12.    - 8:10:2004   12:05 : Created by Kirill Bulatsev
  13.  
  14.  *********************************************************************/
  15.  
  16. #include "StdAfx.h"
  17. #include <CryAISystem/IAISystem.h>
  18. #include <CryAnimation/ICryAnimation.h>
  19. #include <CryNetwork/ISerialize.h>
  20. #include <IActorSystem.h>
  21. #include <IAnimationGraph.h>
  22. #include "AIHandler.h"
  23. #include "AIProxy.h"
  24. #include "PersistantDebug.h"
  25. #include "CryActionCVars.h"
  26. #include <CryAISystem/IBlackBoard.h>
  27. #include <CryAISystem/IAIObject.h>
  28. #include <CryAISystem/IAIActor.h>
  29. //#include <ILipSync.h>
  30. #if defined(__GNUC__)
  31.         #include <float.h>
  32. #endif
  33. #include <CryAISystem/IPathfinder.h>
  34.  
  35. #include <CryAISystem/IAIActor.h>
  36. #include "Mannequin/AnimActionTriState.h"
  37.  
  38. // ============================================================================
  39. // ============================================================================
  40.  
  41. static const int MANNEQUIN_NAVSO_EXACTPOS_PRIORITY = 4; // currently equal to PP_UrgentAction, just above normal actions, but underneath hit death, etc.
  42. static const int MANNEQUIN_EXACTPOS_PRIORITY = 3;       // currently equal to PP_Action, just above movement but underneath urgent actions, hit death, etc.
  43.  
  44. // ============================================================================
  45. // ============================================================================
  46.  
  47. class CAnimActionExactPositioning : public CAnimActionTriState
  48. {
  49. public:
  50.         typedef CAnimActionTriState TBase;
  51.  
  52.         DEFINE_ACTION("ExactPositioning");
  53.  
  54.         CAnimActionExactPositioning(FragmentID fragmentID, IAnimatedCharacter& animChar, bool isOneShot, float maxMiddleDuration, bool isNavSO, const QuatT& targetLocation, IAnimActionTriStateListener* pListener);
  55.  
  56. public:
  57.         inline static bool IsExactPositioningAction(const CAnimActionTriState* pAnimActionTriState)
  58.         {
  59.                 return pAnimActionTriState->GetName()[0] == 'E'; // Horrible, poor man's RTTI
  60.         }
  61.  
  62. private:
  63.         // CAnimActionTriState implementation ---------------------------------------
  64.         virtual void OnEnter() override;
  65.         virtual void OnExit() override;
  66.         // ~CAnimActionTriState implementation --------------------------------------
  67.  
  68. private:
  69.         bool m_isNavSO;
  70. };
  71.  
  72. // ============================================================================
  73. // ============================================================================
  74.  
  75. // ----------------------------------------------------------------------------
  76. CAnimActionExactPositioning::CAnimActionExactPositioning(FragmentID fragmentID, IAnimatedCharacter& animChar, bool isOneShot, float maxMiddleDuration, bool isNavSO, const QuatT& targetLocation, IAnimActionTriStateListener* pListener)
  77.         :
  78.         TBase(
  79.           isNavSO ? MANNEQUIN_NAVSO_EXACTPOS_PRIORITY : MANNEQUIN_EXACTPOS_PRIORITY,
  80.           fragmentID,
  81.           animChar,
  82.           isOneShot,
  83.           maxMiddleDuration,
  84.           false,
  85.           pListener
  86.           ),
  87.         m_isNavSO(isNavSO)
  88. {
  89.         if (m_isNavSO)
  90.         {
  91.                 InitMovementControlMethods(eMCM_Animation, eMCM_Animation);
  92.                 InitTargetLocation(targetLocation);
  93.         }
  94.         else
  95.         {
  96.                 InitMovementControlMethods(eMCM_AnimationHCollision, eMCM_Entity);
  97.         }
  98. }
  99.  
  100. // ----------------------------------------------------------------------------
  101. void CAnimActionExactPositioning::OnEnter()
  102. {
  103.         if (m_isNavSO)
  104.         {
  105.                 m_animChar.RequestPhysicalColliderMode(eColliderMode_Disabled, eColliderModeLayer_Game, "CAnimActionExactPositioning::Enter()");
  106.         }
  107. }
  108.  
  109. // ----------------------------------------------------------------------------
  110. void CAnimActionExactPositioning::OnExit()
  111. {
  112.         if (m_isNavSO)
  113.         {
  114.                 m_animChar.ForceRefreshPhysicalColliderMode();
  115.                 m_animChar.RequestPhysicalColliderMode(eColliderMode_Undefined, eColliderModeLayer_Game, "CAnimActionExactPositioning::Exit()");
  116.         }
  117. }
  118.  
  119. // ============================================================================
  120. // ============================================================================
  121.  
  122. //
  123. //------------------------------------------------------------------------------
  124. CAIHandler::CAIHandler(IGameObject* pGameObject)
  125.         : m_bSoundFinished(false),
  126.         m_pAGState(NULL),
  127.         m_actorTargetStartedQueryID(0),
  128.         m_actorTargetEndQueryID(0),
  129.         m_eActorTargetPhase(eATP_None),
  130.         m_changeActionInputQueryId(0),
  131.         m_changeSignalInputQueryId(0),
  132.         m_playingSignalAnimation(false),
  133.         m_playingActionAnimation(false),
  134.         m_actorTargetId(0),
  135.         m_pGameObject(pGameObject),
  136.         m_pEntity(pGameObject->GetEntity()),
  137.         m_FaceManager(pGameObject->GetEntity()),
  138. #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM
  139.         m_bDelayedCharacterConstructor(false),
  140. #endif
  141.         m_bDelayedBehaviorConstructor(false),
  142.         m_vAnimationTargetPosition(ZERO),
  143.         m_lastTargetType(AITARGET_NONE),
  144.         m_lastTargetThreat(AITHREAT_NONE),
  145.         m_timeSinceEvent(0.0f),
  146.         m_lastTargetID(0),
  147.         m_lastTargetPos(ZERO),
  148.         m_pScriptObject(NULL),
  149.         m_CurrentAlertness(0),
  150.         m_CurrentExclusive(false),
  151.         m_bSignaledAnimationStarted(false),
  152.         m_bAnimationStarted(false)
  153. {
  154.         m_curActorTargetStartedQueryID = &m_actorTargetStartedQueryID;
  155.         m_curActorTargetEndQueryID = &m_actorTargetEndQueryID;
  156. }
  157.  
  158. //
  159. //------------------------------------------------------------------------------
  160. CAIHandler::~CAIHandler(void)
  161. {
  162.         m_animActionTracker.ReleaseAll();
  163.  
  164.         if (m_pAGState)
  165.         {
  166.                 m_pAGState->RemoveListener(this);
  167.         }
  168.  
  169.         IMovementController* pMC = (m_pGameObject ? m_pGameObject->GetMovementController() : NULL);
  170.         if (pMC)
  171.         {
  172.                 pMC->SetExactPositioningListener(NULL);
  173.         }
  174.  
  175.         if (*m_pPreviousBehavior == *m_pBehavior)
  176.                 m_pPreviousBehavior = 0;
  177. }
  178.  
  179. #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM
  180. //
  181. //------------------------------------------------------------------------------
  182. const char* CAIHandler::GetInitialCharacterName()
  183. {
  184.         const char* szAICharacterName = 0;
  185.         SmartScriptTable pEntityProperties;
  186.  
  187.         if (!m_pScriptObject->GetValue("Properties", pEntityProperties))
  188.         {
  189.                 AIWarningID("<CAIHandler> ", "can't find Properties. Entity %s", m_pEntity->GetEntityTextDescription().c_str());
  190.                 return 0;
  191.         }
  192.  
  193.         if (!pEntityProperties->GetValue("aicharacter_character", szAICharacterName))
  194.         {
  195.                 AIWarningID("<CAIHandler> ", "can't find aicharacter_character. Entity %s", m_pEntity->GetEntityTextDescription().c_str());
  196.                 return 0;
  197.         }
  198.  
  199.         return szAICharacterName;
  200. }
  201. #endif
  202.  
  203. //
  204. //------------------------------------------------------------------------------
  205. const char* CAIHandler::GetInitialBehaviorName()
  206. {
  207.         static const ICVar* pModularBehaviorTreeCVar = gEnv->pConsole->GetCVar("ai_ModularBehaviorTree");
  208.         const bool isModularBehaviorTreeEnabled = (pModularBehaviorTreeCVar && pModularBehaviorTreeCVar->GetIVal() != 0);
  209.         if (isModularBehaviorTreeEnabled)
  210.         {
  211.                 SmartScriptTable pEntityProperties;
  212.                 if (m_pScriptObject)
  213.                 {
  214.                         m_pScriptObject->GetValue("Properties", pEntityProperties);
  215.                         if (pEntityProperties)
  216.                         {
  217.                                 const char* behaviorTreeName = 0;
  218.                                 if (pEntityProperties->GetValue("esModularBehaviorTree", behaviorTreeName))
  219.                                 {
  220.                                         const bool hasValidModularBehaviorTreeName = (behaviorTreeName && behaviorTreeName[0] != 0);
  221.                                         if (hasValidModularBehaviorTreeName)
  222.                                         {
  223.                                                 return 0;
  224.                                         }
  225.                                 }
  226.                         }
  227.                 }
  228.         }
  229.  
  230.         SmartScriptTable pEntityPropertiesInstance;
  231.  
  232.         if (!m_pScriptObject || !m_pScriptObject->GetValue("PropertiesInstance", pEntityPropertiesInstance))
  233.         {
  234.                 AIWarningID("<CAIHandler> ", "can't find PropertiesInstance. Entity %s", m_pEntity->GetName());
  235.                 return 0;
  236.         }
  237.  
  238.         const char* szAIBehaviorName = 0;
  239.         if (!pEntityPropertiesInstance.GetPtr())
  240.                 return 0;
  241.         if (!pEntityPropertiesInstance->GetValue("aibehavior_behaviour", szAIBehaviorName))
  242.                 return 0;
  243.  
  244.         return szAIBehaviorName;
  245. }
  246.  
  247. //
  248. //------------------------------------------------------------------------------
  249. void CAIHandler::Init()
  250. {
  251.         m_ActionQueryID = m_SignalQueryID = 0;
  252.         m_sQueriedActionAnimation.clear();
  253.         m_sQueriedSignalAnimation.clear();
  254.         m_bSignaledAnimationStarted = false;
  255.         m_setPlayedSignalAnimations.clear();
  256.         m_setStartedActionAnimations.clear();
  257.         m_animActionTracker.ReleaseAll();
  258.  
  259.         m_pScriptObject = m_pEntity->GetScriptTable();
  260.  
  261.         if (!SetCommonTables())
  262.                 return;
  263.  
  264.         if (IAIObject* aiObject = m_pEntity->GetAI())
  265.         {
  266.                 if (IAIActorProxy* proxy = aiObject->GetProxy())
  267.                 {
  268.                         const char* behaviorSelectionTree = proxy->GetBehaviorSelectionTreeName();
  269.  
  270.                         if (!behaviorSelectionTree || *behaviorSelectionTree == '\0')
  271.                                 SetInitialBehaviorAndCharacter();
  272.                 }
  273.         }
  274.  
  275.         m_pPreviousBehavior = 0;
  276.         m_CurrentAlertness = 0;
  277.         m_CurrentExclusive = false;
  278.  
  279.         // Precache facial animations.
  280.         m_FaceManager.PrecacheSequences();
  281. }
  282.  
  283. //
  284. //------------------------------------------------------------------------------
  285. void CAIHandler::ResetCommonTables()
  286. {
  287.         m_pBehaviorTable = 0;
  288.         m_pBehaviorTableAVAILABLE = 0;
  289.         m_pBehaviorTableINTERNAL = 0;
  290.         m_pDEFAULTDefaultBehavior = 0;
  291. #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM
  292.         m_pDefaultCharacter = 0;
  293. #endif
  294. }
  295.  
  296. //
  297. //------------------------------------------------------------------------------
  298. bool CAIHandler::SetCommonTables()
  299. {
  300.         // Get common tables
  301.         if (!gEnv->pScriptSystem->GetGlobalValue("AIBehavior", m_pBehaviorTable)
  302.             && !gEnv->pScriptSystem->GetGlobalValue("AIBehaviour", m_pBehaviorTable))
  303.         {
  304.                 AIWarningID("<CAIHandler> ", "Can't find AIBehavior table!");
  305.                 return false;
  306.         }
  307.  
  308.         m_pBehaviorTable->GetValue("AVAILABLE", m_pBehaviorTableAVAILABLE);
  309.         m_pBehaviorTable->GetValue("INTERNAL", m_pBehaviorTableINTERNAL);
  310.  
  311.         if (!m_pBehaviorTable->GetValue("DEFAULT", m_pDEFAULTDefaultBehavior))
  312.         {
  313.                 AIWarningID("<CAIHandler> ", "can't find DEFAULT. Entity %s", m_pEntity->GetName());
  314.                 return false;
  315.         }
  316.  
  317. #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM
  318.         SmartScriptTable pCharacterTable;
  319.         if (!gEnv->pScriptSystem->GetGlobalValue("AICharacter", pCharacterTable))
  320.         {
  321.                 AIWarningID("<CAIHandler> ", "can't find AICharacter table. Entity %s", m_pEntity->GetName());
  322.                 return false;
  323.         }
  324.  
  325.         if (!pCharacterTable->GetValue("DEFAULT", m_pDefaultCharacter))
  326.         {
  327.                 AIWarningID("<CAIHandler> ", "can't find DEFAULT character. Entity %s", m_pEntity->GetName());
  328.                 return false;
  329.         }
  330. #endif
  331.  
  332.         return true;
  333. }
  334.  
  335. //
  336. //------------------------------------------------------------------------------
  337. void CAIHandler::SetInitialBehaviorAndCharacter()
  338. {
  339.         const IActor* actor = GetActor();
  340.         const bool isPlayer = actor ? actor->IsPlayer() : false;
  341.  
  342.         if (!isPlayer)
  343.         {
  344. #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM
  345.                 ResetCharacter();
  346. #endif
  347.  
  348.                 ResetBehavior();
  349.  
  350. #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM
  351.                 const char* szDefaultCharacter = GetInitialCharacterName();
  352.                 m_sFirstCharacterName = szDefaultCharacter;
  353.                 if (!SetCharacter(szDefaultCharacter, SET_DELAYED) && !m_sFirstCharacterName.empty())
  354.                         AIWarningID("<CAIHandler> ", "Could not set initial character: %s on Entity: %s",
  355.                                     szDefaultCharacter, m_pEntity->GetEntityTextDescription().c_str());
  356. #endif
  357.  
  358.                 const char* szDefaultBehavior = GetInitialBehaviorName();
  359.                 m_sFirstBehaviorName = szDefaultBehavior;
  360.                 SetBehavior(szDefaultBehavior, 0, SET_DELAYED);
  361.         }
  362. }
  363.  
  364. //
  365. //------------------------------------------------------------------------------
  366. void CAIHandler::ResetAnimationData()
  367. {
  368.         m_ActionQueryID = m_SignalQueryID = 0;
  369.         m_sQueriedActionAnimation.clear();
  370.         m_sQueriedSignalAnimation.clear();
  371.         m_bSignaledAnimationStarted = false;
  372.         m_setPlayedSignalAnimations.clear();
  373.         m_setStartedActionAnimations.clear();
  374.  
  375.         m_playingSignalAnimation = false;
  376.         m_currentSignalAnimName.clear();
  377.         m_playingActionAnimation = false;
  378.         m_currentActionAnimName.clear();
  379.         m_sAGActionSOAutoState.clear();
  380.  
  381.         m_eActorTargetPhase = eATP_None;
  382.         m_actorTargetId = 0;
  383.         m_actorTargetStartedQueryID = 0;
  384.         m_actorTargetEndQueryID = 0;
  385.         m_curActorTargetStartedQueryID = &m_actorTargetStartedQueryID;
  386.         m_curActorTargetEndQueryID = &m_actorTargetEndQueryID;
  387.         m_vAnimationTargetPosition.zero();
  388.         if (IMovementController* pMC = (m_pGameObject ? m_pGameObject->GetMovementController() : NULL))
  389.         {
  390.                 // always clear actor target
  391.                 CMovementRequest mr;
  392.                 mr.ClearActorTarget();
  393.                 pMC->RequestMovement(mr);
  394.         }
  395.         m_animActionTracker.ReleaseAll();
  396. }
  397.  
  398. //
  399. //------------------------------------------------------------------------------
  400. void CAIHandler::Reset(EObjectResetType type)
  401. {
  402.         m_FaceManager.Reset();
  403.  
  404.         ResetAnimationData();
  405.  
  406.         m_bSoundFinished = false;
  407.  
  408.         m_lastTargetType = AITARGET_NONE;
  409.         m_lastTargetThreat = AITHREAT_NONE;
  410.         m_lastTargetID = 0;
  411.         m_lastTargetPos.zero();
  412.  
  413.         m_curActorTargetStartedQueryID = &m_actorTargetStartedQueryID;
  414.         m_curActorTargetEndQueryID = &m_actorTargetEndQueryID;
  415.  
  416.         if (m_pAGState)
  417.         {
  418.                 m_pAGState->RemoveListener(this);
  419.                 m_pAGState = NULL;
  420.         }
  421.  
  422.         IMovementController* pMC = (m_pGameObject ? m_pGameObject->GetMovementController() : NULL);
  423.         if (pMC)
  424.         {
  425.                 pMC->SetExactPositioningListener(this);
  426.         }
  427.  
  428.         m_actorTargetStartedQueryID = 0;
  429.         m_actorTargetEndQueryID = 0;
  430.         m_eActorTargetPhase = eATP_None;
  431.  
  432.         m_CurrentAlertness = 0;
  433.         m_CurrentExclusive = false;
  434.  
  435.         m_pScriptObject = m_pEntity->GetScriptTable();
  436.  
  437.         if (type == AIOBJRESET_SHUTDOWN)
  438.         {
  439. #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM
  440.                 ResetCharacter();
  441. #endif
  442.                 ResetBehavior();
  443.                 ResetCommonTables();
  444.         }
  445.         else
  446.         {
  447.                 SetCommonTables();
  448.  
  449.                 if (IAIObject* aiObject = m_pEntity->GetAI())
  450.                 {
  451.                         if (IAIActorProxy* proxy = aiObject->GetProxy())
  452.                         {
  453.                                 const char* behaviorSelectionTree = proxy->GetBehaviorSelectionTreeName();
  454.  
  455.                                 if (!behaviorSelectionTree || *behaviorSelectionTree == '\0')
  456.                                         SetInitialBehaviorAndCharacter();
  457.                         }
  458.                 }
  459.         }
  460.  
  461.         m_pPreviousBehavior = 0;
  462. #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM
  463.         m_sPrevCharacterName.clear();
  464. #endif
  465.  
  466.         m_timeSinceEvent = 0.0f;
  467. }
  468.  
  469. //
  470. //------------------------------------------------------------------------------
  471. void CAIHandler::OnReused(IGameObject* pGameObject)
  472. {
  473.         assert(pGameObject);
  474.  
  475.         m_pGameObject = pGameObject;
  476.         m_pEntity = pGameObject->GetEntity();
  477.  
  478.         m_FaceManager.OnReused(m_pEntity);
  479.  
  480.         // Reinit
  481.         Init();
  482. }
  483.  
  484. //
  485. //------------------------------------------------------------------------------
  486. void CAIHandler::AIMind(SOBJECTSTATE& state)
  487. {
  488.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  489.  
  490.         bool sameTarget = (m_lastTargetID == state.eTargetID);
  491.         float distSq = m_lastTargetPos.GetSquaredDistance(state.vTargetPos);
  492.  
  493.         /*Note: This needs to be event driven, not done in an update - Morgan 01/10/2011
  494.            //New targets should always signal
  495.            //Using distance in addition here, because group targets get cleared one frame AFTER individual targets.
  496.            //Group target ids will not match for that frame.
  497.          */
  498.         if (sameTarget || distSq < 0.15)
  499.         {
  500.                 //Sounds/Memories/Suspect targets can resignal after a period of time if the target has moved or anything within the same.
  501.                 if ((state.eTargetType == AITARGET_SOUND) ||
  502.                     ((m_lastTargetType == AITARGET_MEMORY) && (state.eTargetType == AITARGET_MEMORY)) ||
  503.                     (state.eTargetThreat == AITHREAT_SUSPECT))
  504.                 {
  505.                         if (!(state.eTargetType > m_lastTargetType || state.eTargetThreat > m_lastTargetThreat))
  506.                         {
  507.                                 m_timeSinceEvent += gEnv->pTimer->GetFrameTime();
  508.  
  509.                                 if (m_timeSinceEvent < 2.0f || distSq < 0.2f)
  510.                                         return;
  511.                         }
  512.                 }
  513.                 //Otherwise use old system, and assume the same target with the same threat/type should not signal.
  514.                 else if ((m_lastTargetType == state.eTargetType) && (m_lastTargetThreat == state.eTargetThreat))
  515.                 {
  516.                         m_timeSinceEvent += gEnv->pTimer->GetFrameTime();
  517.  
  518.                         return;
  519.                 }
  520.         }
  521.  
  522.         m_timeSinceEvent = 0.0f;
  523.  
  524.         EAITargetType prevType = m_lastTargetType;
  525.  
  526.         m_lastTargetType = state.eTargetType;
  527.         m_lastTargetThreat = state.eTargetThreat;
  528.         m_lastTargetID = state.eTargetID;
  529.         m_lastTargetPos = state.vTargetPos;
  530.  
  531.         const char* eventString = 0;
  532.         float* value = 0;
  533.  
  534.         IAISignalExtraData* pExtraData = NULL;
  535.         IAIObject* pEntityAI = m_pEntity->GetAI();
  536.  
  537.         switch (state.eTargetType)
  538.         {
  539.         case AITARGET_MEMORY:
  540.                 //If this a fresh memory, then signal for it
  541.                 if (prevType != AITARGET_MEMORY)
  542.                 {
  543.                         if (state.eTargetThreat == AITHREAT_THREATENING)
  544.                         {
  545.                                 value = &state.fDistanceFromTarget;
  546.                                 eventString = "OnEnemyMemory";
  547.                         }
  548.                         else if (state.eTargetThreat == AITHREAT_AGGRESSIVE)
  549.                         {
  550.                                 value = &state.fDistanceFromTarget;
  551.                                 eventString = "OnLostSightOfTarget";
  552.                         }
  553.                 }
  554.                 else
  555.                 {
  556.                         if (state.eTargetThreat == AITHREAT_AGGRESSIVE)
  557.                         {
  558.                                 value = &state.fDistanceFromTarget;
  559.                                 eventString = "OnMemoryMoved";
  560.                         }
  561.                 }
  562.  
  563.                 break;
  564.         case AITARGET_SOUND:
  565.                 if (state.eTargetThreat >= AITHREAT_AGGRESSIVE)
  566.                 {
  567.                         value = &state.fDistanceFromTarget;
  568.                         eventString = "OnEnemyHeard";
  569.                 }
  570.                 else if (state.eTargetThreat == AITHREAT_THREATENING)
  571.                 {
  572.                         value = &state.fDistanceFromTarget;
  573.                         eventString = "OnThreateningSoundHeard";
  574.                 }
  575.                 else if (state.eTargetThreat == AITHREAT_INTERESTING)
  576.                 {
  577.                         value = &state.fDistanceFromTarget;
  578.                         eventString = "OnInterestingSoundHeard";
  579.                 }
  580.                 else if (state.eTargetThreat == AITHREAT_SUSPECT)
  581.                 {
  582.                         value = &state.fDistanceFromTarget;
  583.                         eventString = "OnSuspectedSoundHeard";
  584.                 }
  585.                 break;
  586.         case AITARGET_VISUAL:
  587.  
  588.                 if (state.nTargetType > AIOBJECT_PLAYER)   //-- grenade (or any other registered object type) seen
  589.                 {
  590.                         FRAME_PROFILER("AI_OnObjectSeen", gEnv->pSystem, PROFILE_AI);
  591.  
  592.                         value = &state.fDistanceFromTarget;
  593.                         if (!pExtraData)
  594.                                 pExtraData = gEnv->pAISystem->CreateSignalExtraData();
  595.                         pExtraData->iValue = state.nTargetType;
  596.  
  597.                         IAIActor* pAIActor = CastToIAIActorSafe(pEntityAI);
  598.                         if (pAIActor)
  599.                         {
  600.                                 IAIObject* pTarget = pAIActor->GetAttentionTarget();
  601.                                 if (pTarget)
  602.                                 {
  603.                                         IEntity* pTargetEntity = (IEntity*)(pTarget->GetEntity());
  604.                                         if (pTargetEntity)
  605.                                         {
  606.                                                 pExtraData->nID = pTargetEntity->GetId();
  607.                                                 pExtraData->point = pTarget->GetPos();
  608.                                                 pe_status_dynamics sd;
  609.                                                 if (pTargetEntity->GetPhysics())
  610.                                                 {
  611.                                                         pTargetEntity->GetPhysics()->GetStatus(&sd);
  612.                                                         pExtraData->point2 = sd.v;
  613.                                                 }
  614.                                                 else
  615.                                                         pExtraData->point2 = ZERO;
  616.                                         }
  617.                                 }
  618.                         }
  619.                         eventString = "OnObjectSeen";
  620.                 }
  621.                 else if (state.eTargetThreat == AITHREAT_AGGRESSIVE)
  622.                 {
  623.                         if (!pExtraData)
  624.                                 pExtraData = gEnv->pAISystem->CreateSignalExtraData();
  625.                         pExtraData->iValue = (int)state.eTargetStuntReaction;
  626.                         state.eTargetStuntReaction = AITSR_NONE;
  627.  
  628.                         FRAME_PROFILER("AI_OnPlayerSeen2", gEnv->pSystem, PROFILE_AI);
  629.                         value = &state.fDistanceFromTarget;
  630.  
  631.                         if (IAIActor* pAIActor = CastToIAIActorSafe(pEntityAI))
  632.                         {
  633.                                 IAIObject* pTarget = pAIActor->GetAttentionTarget();
  634.                                 // sends OnSeenByEnemy to the target
  635.                                 // only if the target can acquire the sender as his target as well
  636.                                 IAIActor* pTargetActor = CastToIAIActorSafe(pTarget);
  637.                                 if (pTargetActor && pTargetActor->CanAcquireTarget(pEntityAI))
  638.                                 {
  639.                                         if (IAIObject::eFOV_Outside != pTarget->IsPointInFOV(pEntityAI->GetPos()))
  640.                                         {
  641.                                                 gEnv->pAISystem->SendSignal(SIGNALFILTER_SENDER, 1, "OnSeenByEnemy", pTarget);
  642.                                         }
  643.                                 }
  644.                         }
  645.  
  646.                         bool targetIsCloaked = false;
  647.                         if (IAIActor* aiActor = CastToIAIActorSafe(pEntityAI))
  648.                                 if (IAIObject* targetAIObecjt = aiActor->GetAttentionTarget())
  649.                                         if (IAIActor* targetAIActor = CastToIAIActorSafe(targetAIObecjt))
  650.                                                 targetIsCloaked = targetAIActor->GetParameters().m_bCloaked;
  651.  
  652.                         if (targetIsCloaked)
  653.                         {
  654.                                 const char* cloakedTargetSeenSignal = "OnCloakedTargetSeen";
  655.                                 AISignal(AISIGNAL_DEFAULT, cloakedTargetSeenSignal, CCrc32::Compute(cloakedTargetSeenSignal), NULL, pExtraData);
  656.                         }
  657.  
  658.                         eventString = "OnEnemySeen";
  659.                 }
  660.                 else if (state.eTargetThreat == AITHREAT_THREATENING)
  661.                 {
  662.                         eventString = "OnThreateningSeen";
  663.                 }
  664.                 else if (state.eTargetThreat == AITHREAT_INTERESTING)
  665.                 {
  666.                         eventString = "OnSomethingSeen";
  667.                 }
  668.                 else if (state.eTargetThreat == AITHREAT_SUSPECT)
  669.                 {
  670.                         eventString = "OnSuspectedSeen";
  671.                 }
  672.                 break;
  673.         case AITARGET_NONE:
  674.                 eventString = "OnNoTarget";
  675.                 break;
  676.         }
  677.  
  678.         if (eventString)
  679.         {
  680.                 gEnv->pAISystem->Record(pEntityAI, IAIRecordable::E_HANDLERNEVENT, eventString);
  681.  
  682.                 IAIRecordable::RecorderEventData recorderEventData(eventString);
  683.                 pEntityAI->RecordEvent(IAIRecordable::E_SIGNALRECIEVED, &recorderEventData);
  684.  
  685.                 AISignal(AISIGNAL_DEFAULT, eventString, CCrc32::Compute(eventString), NULL, pExtraData);
  686.         }
  687.  
  688.         if (pExtraData)
  689.                 gEnv->pAISystem->FreeSignalExtraData(pExtraData);
  690. }
  691.  
  692. //
  693. //------------------------------------------------------------------------------
  694. void CAIHandler::AISignal(int signalID, const char* signalText, uint32 crc, IEntity* pSender, const IAISignalExtraData* pData)
  695. {
  696.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  697.  
  698.         assert(crc != 0);
  699.  
  700.         if (!signalText)
  701.                 return;
  702.  
  703.         if (signalID != AISIGNAL_PROCESS_NEXT_UPDATE)
  704.         {
  705.                 IAIRecordable::RecorderEventData recorderEventData(signalText);
  706.                 m_pEntity->GetAI()->RecordEvent(IAIRecordable::E_SIGNALEXECUTING, &recorderEventData);
  707.                 gEnv->pAISystem->Record(m_pEntity->GetAI(), IAIRecordable::E_SIGNALEXECUTING, signalText);
  708.         }
  709.  
  710.         if (!CallScript(m_pBehavior, signalText, NULL, pSender, pData))
  711.         {
  712. #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM
  713.                 if (!CallScript(m_pDefaultBehavior, signalText, NULL, pSender, pData))
  714.                 {
  715.                         if (CallScript(m_pDEFAULTDefaultBehavior, signalText, NULL, pSender, pData))
  716.                         {
  717.                                 gEnv->pAISystem->Record(m_pEntity->GetAI(), IAIRecordable::E_SIGNALEXECUTING, "from defaultDefault behaviour");
  718.                         }
  719.                 }
  720.                 else
  721.                 {
  722.                         gEnv->pAISystem->Record(m_pEntity->GetAI(), IAIRecordable::E_SIGNALEXECUTING, "from default behaviour");
  723.                 }
  724. #else
  725.                 if (CallScript(m_pDEFAULTDefaultBehavior, signalText, NULL, pSender, pData))
  726.                 {
  727.                         gEnv->pAISystem->Record(m_pEntity->GetAI(), IAIRecordable::E_SIGNALEXECUTING, "from defaultDefault behaviour");
  728.                 }
  729. #endif
  730.         }
  731.  
  732.         if (m_pEntity)
  733.         {
  734.                 CallScript(m_pEntity->GetScriptTable(), signalText, NULL, pSender, pData);
  735.  
  736.                 assert(m_pEntity->GetAI() != NULL);
  737.                 IAIActor* aiActor = m_pEntity->GetAI()->CastToIAIActor();
  738.                 if (aiActor != NULL)
  739.                 {
  740.                         aiActor->OnAIHandlerSentSignal(signalText, crc);
  741.                 }
  742.         }
  743.  
  744. #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM
  745.         if (const char* szNextBehavior = CheckAndGetBehaviorTransition(signalText))
  746.         {
  747.                 SetBehavior(szNextBehavior, pData);
  748.         }
  749. #endif
  750. }
  751.  
  752. #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM
  753. //
  754. //------------------------------------------------------------------------------
  755. const char* CAIHandler::CheckAndGetBehaviorTransition(const char* szSignalText) const
  756. {
  757.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  758.  
  759.         if (!szSignalText || strlen(szSignalText) < 2)
  760.                 return 0;
  761.  
  762.         SmartScriptTable pCharacterTable;
  763.         SmartScriptTable pCharacterDefaultTable;
  764.         SmartScriptTable pNextBehavior;
  765.         const char* szBehaviorName = 0;
  766.         const char* szNextBehaviorName = 0;
  767.  
  768.         if (*m_pBehavior && *m_pCharacter)
  769.         {
  770.                 m_pBehavior->GetValue("Name", szBehaviorName);
  771.                 bool bTable = m_pCharacter->GetValue(szBehaviorName, pCharacterTable);
  772.  
  773.                 if (bTable && pCharacterTable->GetValue(szSignalText, szNextBehaviorName) && !*szNextBehaviorName)
  774.                         return 0;
  775.  
  776.                 bool bDefaultTable = m_pCharacter->GetValue("AnyBehavior", pCharacterDefaultTable);
  777.  
  778.                 if (bTable || bDefaultTable)
  779.                 {
  780.                         if ((bTable && (pCharacterTable->GetValue(szSignalText, szNextBehaviorName) || pCharacterTable->GetValue("_ANY_", szNextBehaviorName))) ||
  781.                             (bDefaultTable && (pCharacterDefaultTable->GetValue(szSignalText, szNextBehaviorName) || pCharacterDefaultTable->GetValue("_ANY_", szNextBehaviorName))))
  782.                         {
  783.                                 if (*szNextBehaviorName)
  784.                                 {
  785.                                         FRAME_PROFILER("Logging of the character change", gEnv->pSystem, PROFILE_AI);
  786.                                         if (m_pEntity && m_pEntity->GetName())
  787.                                         {
  788.                                                 AILogCommentID("<CAIHandler> ", "Entity %s changing behavior from %s to %s on signal %s",
  789.                                                                m_pEntity->GetName(), szBehaviorName ? szBehaviorName : "<null>",
  790.                                                                szNextBehaviorName ? szNextBehaviorName : "<null>", szSignalText ? szSignalText : "<null>");
  791.                                         }
  792.                                         return szNextBehaviorName;
  793.                                 }
  794.                         }
  795.                 }
  796.         }
  797.  
  798.         if (!m_pDefaultCharacter.GetPtr())
  799.                 return 0;
  800.  
  801.         bool tableIsValid = false;
  802.         if (*m_pBehavior)
  803.         {
  804.                 szBehaviorName = m_sBehaviorName.c_str();
  805.                 if (!(tableIsValid = m_pDefaultCharacter->GetValue(szBehaviorName, pCharacterTable)))
  806.                         tableIsValid = m_pDefaultCharacter->GetValue("NoBehaviorFound", pCharacterTable);
  807.         }
  808.         else
  809.                 tableIsValid = m_pDefaultCharacter->GetValue("NoBehaviorFound", pCharacterTable);
  810.  
  811.         if (tableIsValid && pCharacterTable->GetValue(szSignalText, szNextBehaviorName) && *szNextBehaviorName)
  812.         {
  813.                 FRAME_PROFILER("Logging of DEFAULT character change", gEnv->pSystem, PROFILE_AI);
  814.                 if (m_pEntity && m_pEntity->GetName())
  815.                 {
  816.                         AILogCommentID("<CAIHandler> ", "Entity %s changing behavior from %s to %s on signal %s [DEFAULT character]",
  817.                                        m_pEntity->GetName(), szBehaviorName ? szBehaviorName : "<null>",
  818.                                        szNextBehaviorName ? szNextBehaviorName : "<null>", szSignalText ? szSignalText : "<null>");
  819.                 }
  820.                 return szNextBehaviorName;
  821.         }
  822.  
  823.         return 0;
  824. }
  825.  
  826. //
  827. //------------------------------------------------------------------------------
  828. void CAIHandler::ResetCharacter()
  829. {
  830.         // call destructor of current character
  831.         if (m_pCharacter.GetPtr())
  832.         {
  833.                 HSCRIPTFUNCTION pDestructor = 0;
  834.                 if (m_pCharacter->GetValue("Destructor", pDestructor))
  835.                 {
  836.                         gEnv->pScriptSystem->BeginCall(pDestructor);
  837.                         gEnv->pScriptSystem->PushFuncParam(m_pScriptObject);
  838.                         gEnv->pScriptSystem->EndCall();
  839.                 }
  840.         }
  841.  
  842.         m_pCharacter = 0;
  843.         m_sCharacterName.clear();
  844.         m_sDefaultBehaviorName.clear();
  845.         if (m_pScriptObject)
  846.                 m_pScriptObject->SetValue("DefaultBehaviour", m_sDefaultBehaviorName.c_str());
  847.         m_pDefaultBehavior = 0;
  848.         m_bDelayedCharacterConstructor = false;
  849. }
  850.  
  851. //
  852. //------------------------------------------------------------------------------
  853. bool CAIHandler::SetCharacter(const char* szCharacter, ESetFlags setFlags)
  854. {
  855.         if (!szCharacter || !*szCharacter)
  856.         {
  857.                 ResetCharacter();
  858.                 return false;
  859.         }
  860.  
  861.         // only if it's a different one
  862.         if (m_sCharacterName == szCharacter)
  863.                 return true;
  864.  
  865.         SmartScriptTable pCharacterTable; // points to global table AICharacter
  866.         if (!gEnv->pScriptSystem->GetGlobalValue("AICharacter", pCharacterTable))
  867.         {
  868.                 ResetCharacter();
  869.                 return false;
  870.         }
  871.  
  872.         // check is specified character already loaded
  873.         SmartScriptTable pCharacter; // should point to next character table
  874.         if (!pCharacterTable->GetValue(szCharacter, pCharacter))
  875.         {
  876.                 SmartScriptTable pAvailableCharacter;
  877.                 if (!pCharacterTable->GetValue("AVAILABLE", pAvailableCharacter) && !pCharacterTable->GetValue("INTERNAL", pAvailableCharacter))
  878.                 {
  879.                         ResetCharacter();
  880.                         return false;
  881.                 }
  882.  
  883.                 // get file name for specified character
  884.                 const char* szFileName = 0;
  885.                 if (!pAvailableCharacter->GetValue(szCharacter, szFileName))
  886.                 {
  887.                         ResetCharacter();
  888.                         return false;
  889.                 }
  890.  
  891.                 // load the character table
  892.                 if (!gEnv->pScriptSystem->ExecuteFile(szFileName, false, true))
  893.                 {
  894.                         ResetCharacter();
  895.                         return false;
  896.                 }
  897.  
  898.                 // now try to get the table once again
  899.                 if (!pCharacterTable->GetValue(szCharacter, pCharacter))
  900.                 {
  901.                         ResetCharacter();
  902.                         return false;
  903.                 }
  904.         }
  905.  
  906.         // call destructor of current character
  907.         if (setFlags != SET_ON_SERILIAZE)
  908.         {
  909.                 if (m_pCharacter.GetPtr())
  910.                 {
  911.                         HSCRIPTFUNCTION pDestructor = 0;
  912.                         if (m_pCharacter->GetValue("Destructor", pDestructor))
  913.                         {
  914.                                 gEnv->pScriptSystem->BeginCall(pDestructor);
  915.                                 gEnv->pScriptSystem->PushFuncParam(m_pScriptObject);
  916.                                 gEnv->pScriptSystem->EndCall();
  917.                         }
  918.                 }
  919.         }
  920.  
  921.         m_sPrevCharacterName = m_sCharacterName;
  922.         m_sCharacterName = szCharacter;
  923.  
  924.         m_pCharacter = pCharacter;
  925.  
  926.         // adjust default behavior name entry in entity script table
  927.         m_sDefaultBehaviorName = szCharacter;
  928.         m_sDefaultBehaviorName += "Idle";
  929.         m_pScriptObject->SetValue("DefaultBehaviour", m_sDefaultBehaviorName.c_str());
  930.         if (!m_pBehaviorTable.GetPtr())
  931.         {
  932.                 AIWarningID("<CAIHandler> ", "%s m_pBehaviorTable not set up", m_pEntity->GetName());
  933.                 return false;
  934.         }
  935.         if (!FindOrLoadTable(m_pBehaviorTable, m_sDefaultBehaviorName.c_str(), m_pDefaultBehavior))
  936.                 AIWarningID("<CAIHandler> ", "can't find default behaviour %s", m_sDefaultBehaviorName.c_str());
  937.  
  938.         if (setFlags == SET_DELAYED)
  939.         {
  940.                 m_bDelayedCharacterConstructor = true;
  941.         }
  942.         else if (setFlags == SET_IMMEDIATE)
  943.         {
  944.                 m_bDelayedCharacterConstructor = false;
  945.                 CallCharacterConstructor();
  946.         }
  947.  
  948.         return true;
  949. }
  950.  
  951. //
  952. //------------------------------------------------------------------------------
  953. const char* CAIHandler::GetCharacter()
  954. {
  955.         return m_sCharacterName.c_str();
  956. }
  957. #endif
  958.  
  959. //
  960. //------------------------------------------------------------------------------
  961. void CAIHandler::ResetBehavior()
  962. {
  963.         // Finish up with the old behavior.
  964.         if (m_pBehavior.GetPtr())
  965.         {
  966.                 int noPrevious = 0;
  967.                 if (!m_pBehavior->GetValue("NOPREVIOUS", noPrevious))
  968.                         m_pPreviousBehavior = m_pBehavior;
  969.                 // executing behavior destructor
  970.                 CallScript(m_pBehavior, "Destructor", 0, 0, 0);
  971.                 gEnv->pAISystem->Record(m_pEntity->GetAI(), IAIRecordable::E_BEHAVIORDESTRUCTOR, m_sBehaviorName);
  972.         }
  973.  
  974.         m_sBehaviorName.clear();
  975.         m_pBehavior = 0;
  976.         SetAlertness(0, false);
  977.         m_CurrentExclusive = false;
  978.         m_bDelayedBehaviorConstructor = false;
  979. }
  980.  
  981. //
  982. //------------------------------------------------------------------------------
  983. void CAIHandler::SetBehavior(const char* szNextBehaviorName, const IAISignalExtraData* pData, ESetFlags setFlags)
  984. {
  985.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  986.  
  987.         SmartScriptTable pNextBehavior;
  988.  
  989.         if (szNextBehaviorName)
  990.         {
  991.                 if (strcmp(szNextBehaviorName, "PREVIOUS") == 0)
  992.                 {
  993.                         pNextBehavior = m_pPreviousBehavior;
  994.                         if (pNextBehavior.GetPtr())
  995.                         {
  996.                                 const char* szCurBehaviorName = "";
  997.                                 pNextBehavior->GetValue("name", szCurBehaviorName);
  998.  
  999.                                 // Skip ctor/dtor if previous is the same as current behavior.
  1000.                                 if (m_sBehaviorName == szCurBehaviorName)
  1001.                                         return;
  1002.  
  1003.                                 m_sBehaviorName = szNextBehaviorName;
  1004.                         }
  1005.                 }
  1006.                 else
  1007.                 {
  1008.                         if (strcmp(szNextBehaviorName, "FIRST") == 0)
  1009.                                 szNextBehaviorName = m_sFirstBehaviorName.c_str();
  1010.  
  1011.                         FindOrLoadBehavior(szNextBehaviorName, pNextBehavior);
  1012.                 }
  1013.         }
  1014.  
  1015.         IAIObject* aiObject = m_pEntity->GetAI();
  1016.  
  1017.         // Finish up with the old behavior.
  1018.         if (setFlags != SET_ON_SERILIAZE)
  1019.         {
  1020.                 if (m_pBehavior.GetPtr())
  1021.                 {
  1022.                         int noPrevious = 0;
  1023.                         if (!m_pBehavior->GetValue("NOPREVIOUS", noPrevious))
  1024.                         {
  1025.                                 m_pPreviousBehavior = m_pBehavior;
  1026.                         }
  1027.  
  1028.                         // executing behavior destructor
  1029.                         CallScript(m_pBehavior, "Destructor", 0, 0, pData);
  1030.  
  1031.                         gEnv->pAISystem->Record(aiObject, IAIRecordable::E_BEHAVIORDESTRUCTOR, m_sBehaviorName);
  1032.  
  1033.                         if (aiObject)
  1034.                         {
  1035.                                 IAIRecordable::RecorderEventData recorderEventData(m_sBehaviorName);
  1036.                                 aiObject->RecordEvent(IAIRecordable::E_BEHAVIORDESTRUCTOR, &recorderEventData);
  1037.                         }
  1038.                 }
  1039.         }
  1040.  
  1041.         // Switch behavior
  1042.         m_sBehaviorName = szNextBehaviorName;
  1043.         m_pBehavior = pNextBehavior;
  1044.  
  1045.         if (m_pScriptObject)
  1046.         {
  1047.                 m_pScriptObject->SetValue("Behavior", m_pBehavior);
  1048.         }
  1049.  
  1050.         gEnv->pAISystem->Record(aiObject, IAIRecordable::E_BEHAVIORSELECTED, m_sBehaviorName);
  1051.  
  1052.         if (aiObject)
  1053.         {
  1054.                 IAIRecordable::RecorderEventData recorderEventData(m_sBehaviorName);
  1055.                 aiObject->RecordEvent(IAIRecordable::E_BEHAVIORSELECTED, &recorderEventData);
  1056.         }
  1057.  
  1058.         int alertness = m_CurrentAlertness;
  1059.         int exclusive = 0;
  1060.  
  1061.         // Initialize the new behavior
  1062.         if (m_pBehavior.GetPtr())
  1063.         {
  1064.                 m_pBehavior->GetValue("Alertness", alertness) || m_pBehavior->GetValue("alertness", alertness);
  1065.                 m_pBehavior->GetValue("Exclusive", exclusive) || m_pBehavior->GetValue("exclusive", exclusive);
  1066.  
  1067.                 bool leaveCoverOnStart = true;
  1068.                 m_pBehavior->GetValue("LeaveCoverOnStart", leaveCoverOnStart);
  1069.                 if (leaveCoverOnStart)
  1070.                 {
  1071.                         if (IPipeUser* pipeUser = CastToIPipeUserSafe(m_pEntity->GetAI()))
  1072.                                 pipeUser->SetInCover(false);
  1073.                 }
  1074.  
  1075.                 if (setFlags == SET_DELAYED)
  1076.                 {
  1077.                         m_bDelayedBehaviorConstructor = true;
  1078.                         if (pData)
  1079.                         {
  1080.                                 AIWarningID("<CAIHandler::CallScript> ", "SetBehavior: signal extra data ignored for delayed constructor (PipeUser: '%s'; Behaviour: '%s')",
  1081.                                             m_pEntity->GetName(), szNextBehaviorName);
  1082.                         }
  1083.                 }
  1084.                 else if (setFlags == SET_IMMEDIATE)
  1085.                 {
  1086.                         // executing behavior constructor
  1087.                         IAIRecordable::RecorderEventData recorderEventData(szNextBehaviorName);
  1088.                         aiObject->RecordEvent(IAIRecordable::E_BEHAVIORCONSTRUCTOR, &recorderEventData);
  1089.  
  1090.                         m_bDelayedBehaviorConstructor = false;
  1091.                         CallBehaviorConstructor(pData);
  1092.                 }
  1093.         }
  1094.  
  1095.         if (aiObject)
  1096.         {
  1097.                 if (IAIActorProxy* proxy = aiObject->GetProxy())
  1098.                 {
  1099.                         if (IAIActor* actor = aiObject->CastToIAIActor())
  1100.                         {
  1101.                                 // TODO(m谩rcio): Save a ref here instead of going around the world to get to the other side
  1102.                                 const char* currentName = proxy->GetCurrentBehaviorName();
  1103.                                 const char* previousName = proxy->GetPreviousBehaviorName();
  1104.  
  1105.                                 actor->BehaviorChanged(currentName, previousName);
  1106.                         }
  1107.                 }
  1108.         }
  1109.  
  1110.         // Update alertness levels
  1111.         bool bOnAlert = m_CurrentAlertness == 0 && alertness > 0;
  1112.         SetAlertness(alertness, false);
  1113.  
  1114.         // Update behavior exclusive flag
  1115.         m_CurrentExclusive = exclusive > 0;
  1116.  
  1117.         if (setFlags != SET_ON_SERILIAZE)
  1118.         {
  1119.                 if (bOnAlert)
  1120.                 {
  1121.                         SEntityEvent event(ENTITY_EVENT_SCRIPT_EVENT);
  1122.                         event.nParam[0] = (INT_PTR)"OnAlert";
  1123.                         event.nParam[1] = IEntityClass::EVT_BOOL;
  1124.                         bool bValue = true;
  1125.                         event.nParam[2] = (INT_PTR)&bValue;
  1126.                         m_pEntity->SendEvent(event);
  1127.                 }
  1128.         }
  1129. }
  1130.  
  1131. //
  1132. //-------------------------------------------------------------------------------------------------
  1133. void CAIHandler::FindOrLoadBehavior(const char* szBehaviorName, SmartScriptTable& pBehaviorTable)
  1134. {
  1135.         if (!szBehaviorName || !szBehaviorName[0])
  1136.         {
  1137.                 pBehaviorTable = 0;
  1138.                 return;
  1139.         }
  1140.  
  1141.         if (!m_pBehaviorTable.GetPtr())
  1142.                 return;
  1143.  
  1144.         if (!m_pBehaviorTable->GetValue(szBehaviorName, pBehaviorTable))
  1145.         {
  1146.                 //[petar] if behaviour not preloaded then force loading of it
  1147.                 FRAME_PROFILER("On-DemandBehaviourLoading", gEnv->pSystem, PROFILE_AI);
  1148.                 const char* szAIBehaviorFileName = GetBehaviorFileName(szBehaviorName);
  1149.                 if (szAIBehaviorFileName)
  1150.                 {
  1151.                         //fixme - problem with reloading!!!!
  1152.                         gEnv->pScriptSystem->ExecuteFile(szAIBehaviorFileName, true, true);
  1153.  
  1154.                         // M谩rcio: We need to load base behaviors here too!
  1155.                 }
  1156.  
  1157.                 if (!m_pBehaviorTable->GetValue(szBehaviorName, pBehaviorTable))
  1158.                 {
  1159.                         if (m_pEntity && m_pEntity->GetName())
  1160.                         {
  1161.                                 AIWarningID("<CAIHandler> ", "entity %s failed to change behavior to %s.",
  1162.                                             m_pEntity->GetName(), szBehaviorName ? szBehaviorName : "<null>");
  1163.                         }
  1164.                 }
  1165.         }
  1166. }
  1167.  
  1168. #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM
  1169. //
  1170. //------------------------------------------------------------------------------
  1171. void CAIHandler::CallCharacterConstructor()
  1172. {
  1173.         // call character constructor
  1174.         if (m_pCharacter.GetPtr())
  1175.         {
  1176.                 // execute character constructor
  1177.                 HSCRIPTFUNCTION pConstructor = 0;
  1178.                 if (m_pCharacter->GetValue("Constructor", pConstructor))
  1179.                 {
  1180.                         gEnv->pScriptSystem->BeginCall(pConstructor);
  1181.                         gEnv->pScriptSystem->PushFuncParam(m_pCharacter);
  1182.                         gEnv->pScriptSystem->PushFuncParam(m_pScriptObject);
  1183.                         gEnv->pScriptSystem->EndCall();
  1184.                         gEnv->pScriptSystem->ReleaseFunc(pConstructor);
  1185.                 }
  1186.         }
  1187. }
  1188. #endif
  1189.  
  1190. //
  1191. //------------------------------------------------------------------------------
  1192. void CAIHandler::CallBehaviorConstructor(const IAISignalExtraData* pData)
  1193. {
  1194.         if (m_pBehavior.GetPtr())
  1195.         {
  1196.                 gEnv->pAISystem->Record(m_pEntity->GetAI(), IAIRecordable::E_BEHAVIORCONSTRUCTOR, m_sBehaviorName);
  1197.  
  1198.                 IAIActor* pActor = m_pEntity->GetAI()->CastToIAIActor();
  1199.                 if (pActor != NULL)
  1200.                 {
  1201.                         //bool bHas = m_pBehavior->HaveValue( "BlackBoardInit" );
  1202.  
  1203.                         SmartScriptTable behBBInit;
  1204.                         if (m_pBehavior->GetValue("BlackBoardInit", behBBInit) == false)
  1205.                         {
  1206.                                 pActor->GetBehaviorBlackBoard()->Clear();
  1207.                         }
  1208.                         else
  1209.                         {
  1210.                                 pActor->GetBehaviorBlackBoard()->SetFromScript(behBBInit);
  1211.                         }
  1212.                 }
  1213.  
  1214.                 CallScript(m_pBehavior, "Constructor", 0, 0, pData);
  1215.  
  1216.                 const char* szEventToCallName = 0;
  1217.                 if (m_pScriptObject->GetValue("EventToCall", szEventToCallName) && *szEventToCallName)
  1218.                 {
  1219.                         CallScript(m_pBehavior, szEventToCallName);
  1220.                         m_pScriptObject->SetValue("EventToCall", "");
  1221.                 }
  1222.         }
  1223. }
  1224.  
  1225. //
  1226. //------------------------------------------------------------------------------
  1227. void CAIHandler::ResendTargetSignalsNextFrame()
  1228. {
  1229.         m_lastTargetID = 0;
  1230.         m_lastTargetPos.zero();
  1231. }
  1232.  
  1233. //
  1234. //------------------------------------------------------------------------------
  1235. const char* CAIHandler::GetBehaviorFileName(const char* szBehaviorName)
  1236. {
  1237.         const char* szFileName = 0;
  1238.         if (m_pBehaviorTableAVAILABLE.GetPtr() && m_pBehaviorTableAVAILABLE->GetValue(szBehaviorName, szFileName))
  1239.                 return szFileName;
  1240.         else if (m_pBehaviorTableINTERNAL.GetPtr() && m_pBehaviorTableINTERNAL->GetValue(szBehaviorName, szFileName))
  1241.                 return szFileName;
  1242.         return 0;
  1243. }
  1244.  
  1245. //
  1246. //------------------------------------------------------------------------------
  1247. IActor* CAIHandler::GetActor() const
  1248. {
  1249.         CRY_ASSERT(m_pEntity);
  1250.         if (!m_pEntity)
  1251.                 return NULL;
  1252.         IActorSystem* pASystem = gEnv->pGameFramework->GetIActorSystem();
  1253.         if (!pASystem)
  1254.                 return NULL;
  1255.         return pASystem->GetActor(m_pEntity->GetId());
  1256. }
  1257.  
  1258. //
  1259. //------------------------------------------------------------------------------
  1260. bool CAIHandler::CallScript(IScriptTable* scriptTable, const char* funcName, float* pValue, IEntity* pSender, const IAISignalExtraData* pData)
  1261. {
  1262.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  1263.  
  1264.         if (scriptTable)
  1265.         {
  1266.                 HSCRIPTFUNCTION functionToCall = 0;
  1267.  
  1268.                 bool bFound = scriptTable->GetValue(funcName, functionToCall);
  1269.                 if (!bFound)
  1270.                 {
  1271.                         //try parent behaviours
  1272.                         const char* szTableBase;
  1273.                         if (scriptTable->GetValue("Base", szTableBase))
  1274.                         {
  1275.                                 SmartScriptTable scriptTableBase;
  1276.                                 if (m_pBehaviorTable->GetValue(szTableBase, scriptTableBase))
  1277.                                         return CallScript(scriptTableBase, funcName, pValue, pSender, pData);
  1278.                         }
  1279.                 }
  1280.  
  1281.                 if (bFound)
  1282.                 {
  1283. #if !defined(_RELEASE) && !defined(CONSOLE_CONST_CVAR_MODE)
  1284.                         IPersistantDebug* pPD = CCryAction::GetCryAction()->GetIPersistantDebug();
  1285.  
  1286.                         // TODO : (MATT) I don't think we usually do this with statics {2008/01/23:16:30:25}
  1287.                         static ICVar* pAIShowBehaviorCalls = NULL;
  1288.                         if (!pAIShowBehaviorCalls)
  1289.                                 pAIShowBehaviorCalls = gEnv->pConsole->GetCVar("ai_ShowBehaviorCalls");
  1290.  
  1291.                         if (pAIShowBehaviorCalls && pAIShowBehaviorCalls->GetIVal())
  1292.                         {
  1293.                                 SEntityTagParams params;
  1294.                                 char* behaviour = "";
  1295.                                 scriptTable->GetValue("Name", behaviour);
  1296.                                 params.entity = m_pEntity->GetId();
  1297.                                 params.text.Format("%s::%s", behaviour, funcName);
  1298.                                 params.fadeTime = 10.0f;
  1299.                                 params.visibleTime = 5.0f;
  1300.                                 pPD->AddEntityTag(params);
  1301.                         }
  1302. #endif
  1303.                         //                      string str="Calling behavior >> ";
  1304.                         //                      str+= funcName;
  1305.                         //              FRAME_PROFILER( "Calling behavior signal",m_pGame->GetSystem(),PROFILE_AI );
  1306.                         //              FRAME_PROFILER( str.c_str(),m_pGame->GetSystem(),PROFILE_AI );
  1307.  
  1308.                         // only use strings which are known at compile time...
  1309.                         // not doing so causes a stack corruption in the frame profiler -- CW
  1310.                         //              FRAME_PROFILER( funcName,m_pGame->GetSystem(),PROFILE_AI );
  1311.                         //cry_sprintf(m_szSignalName,"AISIGNAL: %s",funcName);
  1312.                         FRAME_PROFILER("AISIGNAL", gEnv->pSystem, PROFILE_AI);
  1313.  
  1314. #ifdef AI_LOG_SIGNALS
  1315.                         static ICVar* pCVarAILogging = NULL;
  1316.                         CTimeValue start;
  1317.                         uint64 pagefaults = 0;
  1318.                         if (CCryActionCVars::Get().aiLogSignals)
  1319.                         {
  1320.                                 if (!pCVarAILogging)
  1321.                                         pCVarAILogging = gEnv->pConsole->GetCVar("ai_enablewarningserrors");
  1322.                                 //float start = pCVarAILogging && pCVarAILogging->GetIVal() ? gEnv->pTimer->GetAsyncCurTime() : 0;
  1323.  
  1324.                                 if (pCVarAILogging && pCVarAILogging->GetIVal())
  1325.                                 {
  1326.                                         start = gEnv->pTimer->GetAsyncTime();
  1327.                                         IMemoryManager::SProcessMemInfo memCounters;
  1328.                                         gEnv->pSystem->GetIMemoryManager()->GetProcessMemInfo(memCounters);
  1329.                                         pagefaults = memCounters.PageFaultCount;
  1330.                                 }
  1331.                         }
  1332. #endif
  1333.  
  1334.                         IScriptSystem* pScriptSystem = gEnv->pScriptSystem;
  1335.                         pScriptSystem->BeginCall(functionToCall);
  1336.  
  1337.                         /*
  1338.                            Francesco: This parameter was used to pass the behavior table as a first
  1339.                            parameter of  LUA functions. Since now we call functions also on the entity
  1340.                            table we can have situation in which the scriptTable and the m_pScriptObject
  1341.                            are the same LUA table.
  1342.                            We can avoid then to push scriptTable as a parameter to allow writing lua functions
  1343.                            of the type
  1344.  
  1345.                            OnFunctionCall = function(entity, sender, data)
  1346.                            ...
  1347.                            end,
  1348.                          */
  1349.  
  1350.                         if (scriptTable != m_pScriptObject)
  1351.                                 pScriptSystem->PushFuncParam(scriptTable);          // self
  1352.  
  1353.                         pScriptSystem->PushFuncParam(m_pScriptObject);
  1354.  
  1355.                         IScriptTable* pScriptTable = pSender ? pSender->GetScriptTable() : NULL;
  1356.                         if (pScriptTable)
  1357.                         {
  1358.                                 pScriptSystem->PushFuncParam(pScriptTable);
  1359.                         }
  1360.                         else
  1361.                         {
  1362.                                 if (pValue)
  1363.                                 {
  1364.                                         pScriptSystem->PushFuncParam(*pValue);
  1365.                                 }
  1366.                                 else
  1367.                                 {
  1368.                                         pScriptSystem->PushFuncParamAny(ANY_TNIL);
  1369.                                 }
  1370.                         }
  1371.  
  1372.                         if (pData)
  1373.                         {
  1374.                                 SmartScriptTable pScriptEData(pScriptSystem);
  1375.                                 pData->ToScriptTable(pScriptEData);
  1376.                                 pScriptSystem->PushFuncParam(*pScriptEData);
  1377.                         }
  1378.  
  1379.                         pScriptSystem->EndCall();
  1380.                         pScriptSystem->ReleaseFunc(functionToCall);
  1381.  
  1382. #ifdef AI_LOG_SIGNALS
  1383.                         if (CCryActionCVars::Get().aiLogSignals)
  1384.                         {
  1385.                                 if (pCVarAILogging && pCVarAILogging->GetIVal())
  1386.                                 {
  1387.                                         start = gEnv->pTimer->GetAsyncTime() - start;
  1388.                                         IMemoryManager::SProcessMemInfo memCounters;
  1389.                                         gEnv->pSystem->GetIMemoryManager()->GetProcessMemInfo(memCounters);
  1390.                                         pagefaults = memCounters.PageFaultCount - pagefaults;
  1391.  
  1392.                                 }
  1393.                                 if (start.GetMilliSeconds() > CCryActionCVars::Get().aiMaxSignalDuration)
  1394.                                 {
  1395.                                         char* behaviour = "";
  1396.                                         scriptTable->GetValue("Name", behaviour);
  1397.                                         AIWarningID("<CAIHandler::CallScript> ", "Handling AISIGNAL '%s' takes %g ms! (PipeUser: '%s'; Behaviour: '%s')",
  1398.                                                     funcName, start.GetMilliSeconds(), m_pEntity->GetName(), behaviour);
  1399.  
  1400.                                         char buffer[256];
  1401.                                         cry_sprintf(buffer, "%s.%s,%g,%d,%s", behaviour, funcName, start.GetMilliSeconds(), (int)pagefaults, m_pEntity->GetName());
  1402.                                         gEnv->pAISystem->Record(m_pEntity->GetAI(), IAIRecordable::E_SIGNALEXECUTEDWARNING, buffer);
  1403.                                 }
  1404.                         }
  1405. #endif
  1406.  
  1407.                         return true;
  1408.                 }
  1409.         }
  1410.         return false;
  1411. }
  1412.  
  1413. //
  1414. //------------------------------------------------------------------------------
  1415. void CAIHandler::Release()
  1416. {
  1417.         delete this;
  1418. }
  1419.  
  1420. //
  1421. //------------------------------------------------------------------------------
  1422. //IScriptTable* CAIHandler::GetMostLikelyTable( IScriptTable* table )
  1423. bool CAIHandler::GetMostLikelyTable(IScriptTable* table, SmartScriptTable& destTable)
  1424. {
  1425.         int numAnims = table->Count();
  1426.         if (!numAnims)
  1427.                 return false;
  1428.  
  1429.         int rangeMin = 0;
  1430.         int rangeMax = 0;
  1431.         int selAnim = -1;
  1432.  
  1433.         int usedCount = 0;
  1434.         int maxProb = 0;
  1435.         int totalProb = 0;
  1436.  
  1437.         // Check the available animations
  1438.         //      CryLog("GetMostLikelyTable:");
  1439.         for (int i = 0; i < numAnims; ++i)
  1440.         {
  1441.                 table->GetAt(i + 1, destTable);
  1442.                 float fProb = 0;
  1443.                 destTable->GetValue("PROBABILITY", fProb);
  1444.                 //              CryLog("%d - %d", i+1, (int)fProb);
  1445.                 totalProb += (int)fProb;
  1446.  
  1447.                 int isUsed = 0;
  1448.                 if (destTable->GetValue("USED", isUsed))
  1449.                 {
  1450.                         //                      CryLog("%d - USED", i+1);
  1451.                         usedCount++;
  1452.                         continue;
  1453.                 }
  1454.  
  1455.                 maxProb += (int)fProb;
  1456.         }
  1457.  
  1458.         if (totalProb < 1000)
  1459.                 maxProb += 1000 - totalProb;
  1460.  
  1461.         // If all anims has been used already, reset.
  1462.         if (usedCount == numAnims)
  1463.         {
  1464.                 for (int i = 0; i < numAnims; ++i)
  1465.                 {
  1466.                         table->GetAt(i + 1, destTable);
  1467.                         destTable->SetToNull("USED");
  1468.                 }
  1469.                 maxProb = 1000;
  1470.         }
  1471.  
  1472.         // Choose among the possible choices
  1473.         int probability = cry_random(0, maxProb - 1);
  1474.  
  1475.         for (int i = 0; i < numAnims; ++i)
  1476.         {
  1477.                 table->GetAt(i + 1, destTable);
  1478.  
  1479.                 // Skip already used ones.
  1480.                 int isUsed = 0;
  1481.                 if (destTable->GetValue("USED", isUsed))
  1482.                         continue;
  1483.  
  1484.                 float fProb = 0;
  1485.                 destTable->GetValue("PROBABILITY", fProb);
  1486.                 rangeMin = rangeMax;
  1487.                 rangeMax += (int)fProb;
  1488.  
  1489.                 if (probability >= rangeMin && probability < rangeMax)
  1490.                 {
  1491.                         selAnim = i + 1;
  1492.                         break;
  1493.                 }
  1494.         }
  1495.  
  1496.         if (selAnim == -1)
  1497.         {
  1498.                 //              CryLog(">> not found!");
  1499.                 return false;
  1500.         }
  1501.  
  1502.         //      CryLog(">> found=%d", selAnim);
  1503.  
  1504.         table->GetAt(selAnim, destTable);
  1505.         destTable->SetValue("USED", 1);
  1506.  
  1507.         return true;
  1508. }
  1509.  
  1510. void CAIHandler::SetAlertness(int value, bool triggerEvent /*=false*/)
  1511. {
  1512.         assert(value <= 2);
  1513.  
  1514.         if (value == -1 || m_CurrentAlertness == value)
  1515.                 return;
  1516.  
  1517.         bool switchToIdle = m_CurrentAlertness > 0 && value == 0;
  1518.         bool switchToWeaponAlerted = m_CurrentAlertness == 0 && value > 0;
  1519.  
  1520.         m_CurrentAlertness = value;
  1521.  
  1522.         if (triggerEvent && switchToWeaponAlerted)
  1523.         {
  1524.                 SEntityEvent event(ENTITY_EVENT_SCRIPT_EVENT);
  1525.                 event.nParam[0] = (INT_PTR)"OnAlert";
  1526.                 event.nParam[1] = IEntityClass::EVT_BOOL;
  1527.                 bool bValue = true;
  1528.                 event.nParam[2] = (INT_PTR)&bValue;
  1529.                 m_pEntity->SendEvent(event);
  1530.         }
  1531.  
  1532.         IActor* const pActor = CCryAction::GetCryAction()->GetIActorSystem()->GetActor(m_pEntity->GetId());
  1533.         if (pActor)
  1534.         {
  1535.                 if (switchToWeaponAlerted)
  1536.                 {
  1537.                         SEntityEvent radarEvent(ENTITY_EVENT_ADD_TO_RADAR);
  1538.                         pActor->ProcessEvent(radarEvent);
  1539.                 }
  1540.                 else if (switchToIdle)
  1541.                 {
  1542.                         SEntityEvent radarEvent(ENTITY_EVENT_REMOVE_FROM_RADAR);
  1543.                         pActor->ProcessEvent(radarEvent);
  1544.                 }
  1545.         }
  1546.  
  1547.         CAIFaceManager::e_ExpressionEvent expression(CAIFaceManager::EE_NONE);
  1548.         const char* sStates = "";
  1549.         switch (m_CurrentAlertness)
  1550.         {
  1551.         case 0: // Idle
  1552.                 sStates = "Idle-Alerted,Combat";
  1553.                 expression = CAIFaceManager::EE_IDLE;
  1554.                 break;
  1555.         case 1: // Alerted
  1556.                 sStates = "Alerted-Idle,Combat";
  1557.                 expression = CAIFaceManager::EE_ALERT;
  1558.                 break;
  1559.         case 2: // Combat
  1560.                 sStates = "Combat-Idle,Alerted";
  1561.                 expression = CAIFaceManager::EE_COMBAT;
  1562.                 break;
  1563.         }
  1564.         MakeFace(expression);
  1565.  
  1566.         if (sStates)
  1567.                 gEnv->pAISystem->GetSmartObjectManager()->ModifySmartObjectStates(m_pEntity, sStates);
  1568. }
  1569.  
  1570. //
  1571. //------------------------------------------------------------------------------
  1572. IActionController* CAIHandler::GetActionController()
  1573. {
  1574.         IActor* pActor = GetActor();
  1575.         if (!pActor)
  1576.                 return NULL;
  1577.  
  1578.         IAnimatedCharacter* pAnimatedCharacter = pActor->GetAnimatedCharacter();
  1579.         if (!pAnimatedCharacter)
  1580.                 return NULL;
  1581.  
  1582.         IActionController* pActionController = pAnimatedCharacter->GetActionController();
  1583.         return pActionController;
  1584. }
  1585.  
  1586. //
  1587. //------------------------------------------------------------------------------
  1588. IAnimationGraphState* CAIHandler::GetAGState()
  1589. {
  1590.         if (m_pAGState)
  1591.                 return m_pAGState;
  1592.  
  1593.         IActor* pActor = GetActor();
  1594.         if (!pActor)
  1595.                 return NULL;
  1596.         m_pAGState = pActor->GetAnimationGraphState();
  1597.         if (!m_pAGState)
  1598.                 return NULL;
  1599.  
  1600.         if (!GetActionController())
  1601.         {
  1602.                 // When using Mannequin, we don't need to wait for these
  1603.                 // signals anymore.
  1604.                 m_pAGState->QueryChangeInput(GetAGInputName(AIAG_ACTION), &m_changeActionInputQueryId);
  1605.                 m_pAGState->QueryChangeInput(GetAGInputName(AIAG_SIGNAL), &m_changeSignalInputQueryId);
  1606.         }
  1607.  
  1608.         m_pAGState->AddListener("AIHandler", this);
  1609.         return m_pAGState;
  1610. }
  1611.  
  1612. bool CAIHandler::IsAnimationBlockingMovement() const
  1613. {
  1614.         IActor* pActor = const_cast<IActor*>(GetActor());
  1615.         if (pActor)
  1616.         {
  1617.                 const IAnimatedCharacter* pAnimChar = pActor->GetAnimatedCharacter();
  1618.                 return pAnimChar && (pAnimChar->GetMCMH() == eMCM_Animation || pAnimChar->GetMCMH() == eMCM_AnimationHCollision)
  1619.                        && (m_bSignaledAnimationStarted || m_playingActionAnimation);
  1620.         }
  1621.         else
  1622.         {
  1623.                 return false;
  1624.         }
  1625. }
  1626.  
  1627. //////////////////////////////////////////////////////////////////////////
  1628. void CAIHandler::HandleCoverRequest(SOBJECTSTATE& state, CMovementRequest& mr)
  1629. {
  1630.         IActionController* pActionController = GetActionController();
  1631.         if (pActionController)
  1632.         {
  1633.                 // Safety check to handle invalid coverlocations
  1634.                 {
  1635.                         const EStance stance = (EStance)state.bodystate;
  1636.                         const bool isInCoverStance = (stance == STANCE_HIGH_COVER) || (stance == STANCE_LOW_COVER);
  1637.                         if (isInCoverStance)
  1638.                         {
  1639.                                 if (state.coverRequest.coverLocationRequest == eCoverLocationRequest_Set)
  1640.                                 {
  1641.                                         QuatT& coverLocation = state.coverRequest.coverLocation;
  1642.                                         CRY_ASSERT(coverLocation.IsValid());
  1643.  
  1644.                                         const float TOO_FAR_AWAY = 50.0f;
  1645.                                         if (coverLocation.t.GetSquaredDistance2D(m_pEntity->GetPos()) >= sqr(TOO_FAR_AWAY))
  1646.                                         {
  1647.                                                 CRY_ASSERT_MESSAGE(false, "Cover stance requested but CoverLocation is too far away from the entity");
  1648.                                                 state.coverRequest.coverLocationRequest = eCoverLocationRequest_Clear;
  1649.                                         }
  1650.                                 }
  1651.                         }
  1652.                 }
  1653.  
  1654.                 mr.SetAICoverRequest(state.coverRequest);
  1655.         }
  1656.  
  1657.         state.coverRequest = SAICoverRequest();
  1658. }
  1659.  
  1660. //////////////////////////////////////////////////////////////////////////
  1661. void CAIHandler::HandleMannequinRequest(SOBJECTSTATE& state, CMovementRequest& mr)
  1662. {
  1663.         SMannequinTagRequest tagRequest;
  1664.  
  1665.         IActionController* pActionController = GetActionController();
  1666.         if (pActionController)
  1667.         {
  1668.                 const CTagDefinition& tagDef = pActionController->GetContext().controllerDef.m_tags;
  1669.                 const aiMannequin::SCommand* pCommand = state.mannequinRequest.GetFirstCommand();
  1670.                 while (pCommand)
  1671.                 {
  1672.                         const uint16 commandType = pCommand->m_type;
  1673.                         switch (commandType)
  1674.                         {
  1675.                         case aiMannequin::eMC_SetTag:
  1676.                                 {
  1677.                                         const aiMannequin::STagCommand* pTagCommand = static_cast<const aiMannequin::STagCommand*>(pCommand);
  1678.                                         const uint32 tagCrc = pTagCommand->m_tagCrc;
  1679.                                         const TagID tagId = tagDef.Find(tagCrc);
  1680.                                         if (tagId != TAG_ID_INVALID)
  1681.                                         {
  1682.                                                 tagDef.Set(tagRequest.setTags, tagId, true);
  1683.                                         }
  1684.                                 }
  1685.                                 break;
  1686.  
  1687.                         case aiMannequin::eMC_ClearTag:
  1688.                                 {
  1689.                                         const aiMannequin::STagCommand* pTagCommand = static_cast<const aiMannequin::STagCommand*>(pCommand);
  1690.                                         const uint32 tagCrc = pTagCommand->m_tagCrc;
  1691.                                         const TagID tagId = tagDef.Find(tagCrc);
  1692.                                         if (tagId != TAG_ID_INVALID)
  1693.                                         {
  1694.                                                 tagDef.Set(tagRequest.clearTags, tagId, true);
  1695.                                                 tagDef.Set(tagRequest.setTags, tagId, false);
  1696.                                         }
  1697.                                 }
  1698.                                 break;
  1699.  
  1700.                         default:
  1701.                                 CRY_ASSERT(false);
  1702.                         }
  1703.  
  1704.                         pCommand = state.mannequinRequest.GetNextCommand(pCommand);
  1705.                 }
  1706.         }
  1707.  
  1708.         mr.SetMannequinTagRequest(tagRequest);
  1709.         state.mannequinRequest.ClearCommands();
  1710. }
  1711.  
  1712. // ----------------------------------------------------------------------------
  1713. CAnimActionExactPositioning* CAIHandler::CreateExactPositioningAction(bool isOneShot, const float loopDuration, const char* szFragmentID, bool isNavigationalSO, const QuatT& exactStartLocation)
  1714. {
  1715.         IActor* pActor = GetActor();
  1716.         if (!pActor)
  1717.                 return NULL;
  1718.  
  1719.         IAnimatedCharacter* pAnimatedCharacter = pActor->GetAnimatedCharacter();
  1720.         if (!pAnimatedCharacter)
  1721.                 return NULL;
  1722.  
  1723.         IActionController* pActionController = pAnimatedCharacter->GetActionController();
  1724.         if (!pActionController)
  1725.                 return NULL;
  1726.  
  1727.         const uint32 valueCRC = CCrc32::ComputeLowercase(szFragmentID);
  1728.  
  1729.         bool isDefaultValue = true;
  1730.         if (isOneShot)
  1731.         {
  1732.                 static const uint32 noneCRC = CCrc32::ComputeLowercase("none");
  1733.                 isDefaultValue = (valueCRC == noneCRC);
  1734.         }
  1735.         else
  1736.         {
  1737.                 static const uint32 idleCRC = CCrc32::ComputeLowercase("idle");
  1738.                 isDefaultValue = (valueCRC == idleCRC);
  1739.         }
  1740.  
  1741.         if (!valueCRC)
  1742.         {
  1743.                 CRY_ASSERT(false); // no signal or action was selected, or we're extremely unlucky and hit a 0 CRC
  1744.                 return NULL;
  1745.         }
  1746.  
  1747.         CRY_ASSERT(!isDefaultValue);
  1748.         if (isDefaultValue)
  1749.                 return NULL;
  1750.  
  1751.         FragmentID fragmentID = pActionController->GetContext().controllerDef.m_fragmentIDs.Find(valueCRC);
  1752.         if (fragmentID == FRAGMENT_ID_INVALID)
  1753.         {
  1754.                 const IEntity* pEntity = pAnimatedCharacter->GetEntity();
  1755.  
  1756.                 CryWarning(
  1757.                   VALIDATOR_MODULE_GAME,
  1758.                   VALIDATOR_WARNING,
  1759.                   "AIHandler: Fragment '%s' not found (entity = '%s'; controllerDef = '%s')",
  1760.                   szFragmentID,
  1761.                   pEntity ? pEntity->GetName() : "<invalid>",
  1762.                   pActionController->GetContext().controllerDef.m_filename.c_str());
  1763.  
  1764.                 return NULL;
  1765.         }
  1766.  
  1767.         const bool keepTrackOfAction = !isNavigationalSO;
  1768.         CAnimActionExactPositioning* pAction = new CAnimActionExactPositioning(fragmentID, *pAnimatedCharacter, isOneShot, isOneShot ? -1 : loopDuration, isNavigationalSO, exactStartLocation, keepTrackOfAction ? this : NULL);
  1769.  
  1770.         if (keepTrackOfAction)
  1771.                 m_animActionTracker.Add(pAction);
  1772.  
  1773.         return pAction;
  1774. }
  1775.  
  1776. //
  1777. //------------------------------------------------------------------------------
  1778. void CAIHandler::HandleExactPositioning(SOBJECTSTATE& state, CMovementRequest& mr)
  1779. {
  1780.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  1781.  
  1782.         IMovementController* pMC = (m_pGameObject ? m_pGameObject->GetMovementController() : NULL);
  1783.         if (!pMC)
  1784.                 return;
  1785.  
  1786.         // Register this as the target point verifier to ensure we know when EP position target has been reached
  1787.         pMC->SetExactPositioningListener(this);
  1788.  
  1789.         // The AIsystem is reported back the same phase that we handle here.
  1790.         state.curActorTargetPhase = m_eActorTargetPhase;
  1791.  
  1792.         if (m_actorTargetId != state.actorTargetReq.id)
  1793.         {
  1794.                 const SExactPositioningTarget* animTgt = pMC->GetExactPositioningTarget();
  1795.  
  1796.                 if ((!animTgt || !animTgt->activated) &&
  1797.                     state.curActorTargetPhase != eATP_Started &&
  1798.                     state.curActorTargetPhase != eATP_Playing &&
  1799.                     state.curActorTargetPhase != eATP_StartedAndFinished &&
  1800.                     state.curActorTargetPhase != eATP_Finished)
  1801.                 {
  1802.                         if (state.actorTargetReq.id == 0)
  1803.                         {
  1804.                                 m_eActorTargetPhase = eATP_None;
  1805.                                 *m_curActorTargetStartedQueryID = 0;
  1806.                                 *m_curActorTargetEndQueryID = 0;
  1807.                                 mr.ClearActorTarget();
  1808.                         }
  1809.                         else
  1810.                         {
  1811.                                 m_eActorTargetPhase = eATP_Waiting;
  1812.  
  1813.                                 // if the requester passes us IDs use them instead of the local ones.
  1814.                                 if (state.actorTargetReq.pQueryStart && state.actorTargetReq.pQueryEnd)
  1815.                                 {
  1816.                                         m_curActorTargetStartedQueryID = state.actorTargetReq.pQueryStart;
  1817.                                         m_curActorTargetEndQueryID = state.actorTargetReq.pQueryEnd;
  1818.                                 }
  1819.                                 else
  1820.                                 {
  1821.                                         m_curActorTargetStartedQueryID = &m_actorTargetStartedQueryID;
  1822.                                         m_curActorTargetEndQueryID = &m_actorTargetEndQueryID;
  1823.                                 }
  1824.  
  1825.                                 *m_curActorTargetStartedQueryID = 0;
  1826.                                 *m_curActorTargetEndQueryID = 0;
  1827.  
  1828.                                 SActorTargetParams actorTarget;
  1829.                                 actorTarget.location = state.actorTargetReq.animLocation;
  1830.                                 actorTarget.startArcAngle = state.actorTargetReq.startArcAngle;
  1831.                                 actorTarget.startWidth = state.actorTargetReq.startWidth;
  1832.                                 actorTarget.direction = state.actorTargetReq.animDirection.GetNormalizedSafe(ZERO);
  1833.                                 actorTarget.directionTolerance = state.actorTargetReq.directionTolerance;
  1834.                                 if (actorTarget.direction.IsZero())
  1835.                                 {
  1836.                                         actorTarget.direction = FORWARD_DIRECTION;
  1837.                                         actorTarget.directionTolerance = gf_PI;
  1838.                                 }
  1839.                                 actorTarget.speed = -1;
  1840.                                 actorTarget.vehicleName = state.actorTargetReq.vehicleName;
  1841.                                 actorTarget.vehicleSeat = state.actorTargetReq.vehicleSeat;
  1842.                                 actorTarget.projectEnd = actorTarget.vehicleName.empty() && state.actorTargetReq.projectEndPoint;
  1843.                                 actorTarget.navSO = state.actorTargetReq.lowerPrecision;
  1844.  
  1845.                                 actorTarget.stance = state.actorTargetReq.stance;
  1846.                                 actorTarget.pQueryStart = m_curActorTargetStartedQueryID;
  1847.                                 actorTarget.pQueryEnd = m_curActorTargetEndQueryID;
  1848.  
  1849.                                 CAnimActionExactPositioning* pAction = CreateExactPositioningAction(
  1850.                                   state.actorTargetReq.signalAnimation,
  1851.                                   state.actorTargetReq.loopDuration,
  1852.                                   state.actorTargetReq.animation,
  1853.                                   actorTarget.navSO,
  1854.                                   QuatT(actorTarget.location, Quat::CreateRotationV0V1(FORWARD_DIRECTION, actorTarget.direction)));
  1855.  
  1856.                                 actorTarget.pAction = pAction;
  1857.  
  1858.                                 actorTarget.completeWhenActivated = false;
  1859.  
  1860.                                 mr.SetActorTarget(actorTarget);
  1861.                         }
  1862.  
  1863.                         m_vAnimationTargetPosition.zero();
  1864.                         state.curActorTargetPhase = m_eActorTargetPhase;
  1865.                         m_actorTargetId = state.actorTargetReq.id;
  1866.                         return;
  1867.                 }
  1868.         }
  1869.  
  1870.         if (m_eActorTargetPhase == eATP_Waiting)
  1871.         {
  1872.                 //              if(state.actorTargetPhase == eATP_Waiting)
  1873.                 {
  1874.                         const SExactPositioningTarget* animTgt = pMC->GetExactPositioningTarget();
  1875.  
  1876.                         if (!animTgt)
  1877.                         {
  1878.                                 // exact positioning request was made but was invalid or cleared after some time without any notification :-(
  1879.  
  1880.                                 // Jonas: This failure is not acceptable.
  1881.                                 assert(0);
  1882.                                 m_eActorTargetPhase = eATP_Error;
  1883.                                 state.curActorTargetPhase = eATP_Error;
  1884.  
  1885.                                 //                              m_actorTargetStartedQueryID = 0;
  1886.                                 //                      m_bAnimationStarted = false;
  1887.                         }
  1888.                 }
  1889.         }
  1890.         else if (m_eActorTargetPhase == eATP_Starting)
  1891.         {
  1892.                 // Waiting for starting position.
  1893.         }
  1894.         else if (m_eActorTargetPhase == eATP_Started)
  1895.         {
  1896.                 // Wait until we get a animation target back too.
  1897.                 m_eActorTargetPhase = eATP_Playing;
  1898.         }
  1899.         else if (m_eActorTargetPhase == eATP_Playing)
  1900.         {
  1901.                 // empty
  1902.         }
  1903.         else if (m_eActorTargetPhase == eATP_StartedAndFinished)
  1904.         {
  1905.                 m_eActorTargetPhase = eATP_None;
  1906.         }
  1907.         else if (m_eActorTargetPhase == eATP_Finished)
  1908.         {
  1909.                 m_eActorTargetPhase = eATP_None;
  1910.         }
  1911.         else if (m_eActorTargetPhase == eATP_Error)
  1912.         {
  1913.                 if (state.actorTargetReq.id == 0)
  1914.                         m_eActorTargetPhase = eATP_None;
  1915.         }
  1916.  
  1917.         state.curActorTargetFinishPos = m_vAnimationTargetPosition;
  1918.  
  1919.         if (m_eActorTargetPhase == eATP_None)
  1920.         {
  1921.                 // make sure there's nothing hanging around in the system
  1922.                 mr.ClearActorTarget();
  1923.                 m_vAnimationTargetPosition.zero();
  1924.                 m_actorTargetStartedQueryID = 0;
  1925.                 m_actorTargetEndQueryID = 0;
  1926.         }
  1927. }
  1928.  
  1929. void CAIHandler::QueryComplete(TAnimationGraphQueryID queryID, bool succeeded)
  1930. {
  1931.         if (queryID == m_ActionQueryID)
  1932.         {
  1933.                 CRY_ASSERT(!GetActionController()); // this code-path should not be called anymore when using mannequin
  1934.  
  1935.                 if (!m_sQueriedActionAnimation.empty())
  1936.                 {
  1937.                         m_setStartedActionAnimations.insert(m_sQueriedActionAnimation);
  1938.                         m_sQueriedActionAnimation.clear();
  1939.                 }
  1940.         }
  1941.         else if (queryID == m_SignalQueryID)
  1942.         {
  1943.                 CRY_ASSERT(!GetActionController()); // this code-path should not be called anymore when using mannequin
  1944.  
  1945.                 if (m_bSignaledAnimationStarted || !succeeded)
  1946.                 {
  1947.                         if (!m_sQueriedSignalAnimation.empty() || !succeeded)
  1948.                         {
  1949.                                 m_setPlayedSignalAnimations.insert(m_sQueriedSignalAnimation);
  1950.                                 m_sQueriedSignalAnimation.clear();
  1951.                         }
  1952.                         m_bSignaledAnimationStarted = false;
  1953.                 }
  1954.                 else if (!m_sQueriedSignalAnimation.empty())
  1955.                 {
  1956.                         GetAGState()->QueryLeaveState(&m_SignalQueryID);
  1957.                         m_bSignaledAnimationStarted = true;
  1958.                 }
  1959.         }
  1960.         else if (queryID == m_changeActionInputQueryId)
  1961.         {
  1962.                 CRY_ASSERT(!GetActionController()); // this code-path should not be called anymore when using mannequin
  1963.  
  1964.                 AnimationGraphInputID idAction = m_pAGState->GetInputId(GetAGInputName(AIAG_ACTION));
  1965.                 char value[64] = "\0";
  1966.                 string newValue;
  1967.                 m_pAGState->GetInput(idAction, value);
  1968.  
  1969.                 bool defaultValue = m_pAGState->IsDefaultInputValue(idAction);   // _stricmp(value,"idle") == 0 || _stricmp(value,"weaponAlerted") == 0 || _stricmp(value,"<<not set>>") == 0;
  1970.                 if (!defaultValue)
  1971.                         newValue = value;
  1972.  
  1973.                 m_playingActionAnimation = !defaultValue;
  1974.  
  1975.                 if (m_playingActionAnimation)
  1976.                         m_currentActionAnimName = value;
  1977.                 else
  1978.                         m_currentActionAnimName.clear();
  1979.  
  1980.                 // update smart object state if changed
  1981.                 if (m_sAGActionSOAutoState != newValue)
  1982.                 {
  1983.                         if (!m_sAGActionSOAutoState.empty())
  1984.                                 gEnv->pAISystem->GetSmartObjectManager()->RemoveSmartObjectState(m_pEntity, m_sAGActionSOAutoState);
  1985.                         m_sAGActionSOAutoState = newValue;
  1986.                         if (!m_sAGActionSOAutoState.empty())
  1987.                                 gEnv->pAISystem->GetSmartObjectManager()->AddSmartObjectState(m_pEntity, m_sAGActionSOAutoState);
  1988.                 }
  1989.  
  1990.                 // query the next change
  1991.                 if (idAction != (AnimationGraphInputID) ~0)
  1992.                 {
  1993.                         m_pAGState->QueryChangeInput(idAction, &m_changeActionInputQueryId);
  1994.                 }
  1995.         }
  1996.         else if (queryID == m_changeSignalInputQueryId)
  1997.         {
  1998.                 CRY_ASSERT(!GetActionController()); // this code-path should not be called anymore when using mannequin
  1999.  
  2000.                 AnimationGraphInputID idSignal = m_pAGState->GetInputId(GetAGInputName(AIAG_SIGNAL));
  2001.                 char value[64] = "\0";
  2002.                 m_pAGState->GetInput(idSignal, value);
  2003.  
  2004.                 bool defaultValue = m_pAGState->IsDefaultInputValue(idSignal);    // _stricmp(value,"none") == 0 || _stricmp(value,"<<not set>>") == 0;
  2005.  
  2006.                 m_playingSignalAnimation = !defaultValue;
  2007.                 if (m_playingSignalAnimation)
  2008.                         m_currentSignalAnimName = value;
  2009.                 else
  2010.                         m_currentSignalAnimName.clear();
  2011.  
  2012.                 // query the next change
  2013.                 if (idSignal != (AnimationGraphInputID) ~0)
  2014.                 {
  2015.                         m_pAGState->QueryChangeInput(idSignal, &m_changeSignalInputQueryId);
  2016.                 }
  2017.         }
  2018.         else if (queryID == *m_curActorTargetStartedQueryID)
  2019.         {
  2020.                 if (succeeded)
  2021.                 {
  2022.                         if (m_eActorTargetPhase == eATP_Waiting)
  2023.                         {
  2024.                                 m_eActorTargetPhase = eATP_Starting;
  2025.                                 m_vAnimationTargetPosition.zero();
  2026.                                 m_qAnimationTargetOrientation.SetIdentity();
  2027.                         }
  2028.                         else
  2029.                         {
  2030.                                 // Jonas: This is not acceptable.
  2031.                                 m_eActorTargetPhase = eATP_Error;
  2032.                         }
  2033.                 }
  2034.                 else
  2035.                 {
  2036.                         // Jonas: This is not acceptable.
  2037.                         assert(0);
  2038.                         m_eActorTargetPhase = eATP_Error;
  2039.                 }
  2040.                 //              *m_curActorTargetStartedQueryID = 0;
  2041.         }
  2042.         else if (queryID == *m_curActorTargetEndQueryID)
  2043.         {
  2044.                 if (succeeded)
  2045.                 {
  2046.                         // It is possible the the animation starts and stops before the AI gets a change to update.
  2047.                         if (m_eActorTargetPhase == eATP_Starting || m_eActorTargetPhase == eATP_Started)
  2048.                         {
  2049.                                 m_eActorTargetPhase = eATP_StartedAndFinished;
  2050.                         }
  2051.                         else if (m_eActorTargetPhase == eATP_Playing)
  2052.                         {
  2053.                                 m_eActorTargetPhase = eATP_Finished;
  2054.                         }
  2055.                         else
  2056.                         {
  2057.                                 CRY_ASSERT(0);
  2058.                                 m_eActorTargetPhase = eATP_Error;
  2059.                         }
  2060.                 }
  2061.                 else
  2062.                 {
  2063.                         // Jonas: This is not acceptable.
  2064.                         assert(0);
  2065.                         m_eActorTargetPhase = eATP_Error;
  2066.                 }
  2067.                 //              *m_curActorTargetEndQueryID = 0;
  2068.         }
  2069. }
  2070.  
  2071. void CAIHandler::DestroyedState(IAnimationGraphState* pAGState)
  2072. {
  2073.         if (pAGState == m_pAGState)
  2074.                 m_pAGState = NULL;
  2075. }
  2076.  
  2077. //
  2078. //----------------------------------------------------------------------------------------------------------
  2079. void CAIHandler::ExactPositioningNotifyFinishPoint(const Vec3& pt)
  2080. {
  2081.         m_vAnimationTargetPosition = pt;
  2082.         if (m_eActorTargetPhase == eATP_Starting || m_eActorTargetPhase == eATP_Waiting)
  2083.                 m_eActorTargetPhase = eATP_Started;
  2084. }
  2085.  
  2086. void CAIHandler::ExactPositioningQueryComplete(TExactPositioningQueryID queryID, bool succeeded)
  2087. {
  2088.         if (queryID == *m_curActorTargetStartedQueryID)
  2089.         {
  2090.                 if (succeeded)
  2091.                 {
  2092.                         if (m_eActorTargetPhase == eATP_Waiting)
  2093.                         {
  2094.                                 m_eActorTargetPhase = eATP_Starting;
  2095.                                 m_vAnimationTargetPosition.zero();
  2096.                                 m_qAnimationTargetOrientation.SetIdentity();
  2097.                         }
  2098.                         else
  2099.                         {
  2100.                                 // Jonas: This is not acceptable.
  2101.                                 m_eActorTargetPhase = eATP_Error;
  2102.                         }
  2103.                 }
  2104.                 else
  2105.                 {
  2106.                         // Jonas: This is not acceptable.
  2107.                         assert(0);
  2108.                         m_eActorTargetPhase = eATP_Error;
  2109.                 }
  2110.                 //              *m_curActorTargetStartedQueryID = 0;
  2111.         }
  2112.         else if (queryID == *m_curActorTargetEndQueryID)
  2113.         {
  2114.                 if (succeeded)
  2115.                 {
  2116.                         // It is possible the the animation starts and stops before the AI gets a change to update.
  2117.                         if (m_eActorTargetPhase == eATP_Starting || m_eActorTargetPhase == eATP_Started)
  2118.                         {
  2119.                                 m_eActorTargetPhase = eATP_StartedAndFinished;
  2120.                         }
  2121.                         else if (m_eActorTargetPhase == eATP_Playing)
  2122.                         {
  2123.                                 m_eActorTargetPhase = eATP_Finished;
  2124.                         }
  2125.                         else
  2126.                         {
  2127.                                 CRY_ASSERT(0);
  2128.                                 m_eActorTargetPhase = eATP_Error;
  2129.                         }
  2130.                 }
  2131.                 else
  2132.                 {
  2133.                         // Jonas: This is not acceptable.
  2134.                         assert(0);
  2135.                         m_eActorTargetPhase = eATP_Error;
  2136.                 }
  2137.                 //              *m_curActorTargetEndQueryID = 0;
  2138.         }
  2139. }
  2140.  
  2141. //
  2142. //------------------------------------------------------------------------------
  2143. CTimeValue CAIHandler::GetEstimatedAGAnimationLength(EAIAGInput input, const char* value)
  2144. {
  2145.         CTimeValue length;
  2146.  
  2147.         IAnimationGraphState* pAGState = GetAGState();
  2148.         if (!pAGState)
  2149.                 return length;
  2150.  
  2151.         IAnimationGraphExistanceQuery* pQuery = NULL;
  2152.         for (int layerIndex = 0; pQuery = pAGState->CreateExistanceQuery(layerIndex); layerIndex++)
  2153.         {
  2154.                 pQuery->SetInput(GetAGInputName(input), value);
  2155.  
  2156.                 if (pQuery->Complete())
  2157.                 {
  2158.                         length = max<CTimeValue>(length, pQuery->GetAnimationLength());
  2159.                 }
  2160.  
  2161.                 pQuery->Release();
  2162.         }
  2163.  
  2164.         return length;
  2165. }
  2166.  
  2167. //
  2168. //------------------------------------------------------------------------------
  2169. bool CAIHandler::SetAGInput(EAIAGInput input, const char* value, const bool isUrgent)
  2170. {
  2171.         IActionController* pActionController = GetActionController();
  2172.         if (pActionController)
  2173.                 return SetMannequinAGInput(pActionController, input, value, isUrgent);
  2174.  
  2175.         return false;
  2176. }
  2177.  
  2178. bool CAIHandler::ResetAGInput(EAIAGInput input)
  2179. {
  2180.         IActionController* pActionController = GetActionController();
  2181.         if (pActionController)
  2182.                 return ResetMannequinAGInput(input);
  2183.  
  2184.         return false;
  2185. }
  2186.  
  2187. bool CAIHandler::IsSignalAnimationPlayed(const char* value)
  2188. {
  2189.         if (stl::member_find_and_erase(m_setPlayedSignalAnimations, value))
  2190.         {
  2191.                 return true;
  2192.         }
  2193.         return m_sQueriedSignalAnimation != value;
  2194. }
  2195.  
  2196. bool CAIHandler::IsActionAnimationStarted(const char* value)
  2197. {
  2198.         if (stl::member_find_and_erase(m_setStartedActionAnimations, value))
  2199.         {
  2200.                 return true;
  2201.         }
  2202.         return m_sQueriedActionAnimation != value;
  2203. }
  2204.  
  2205. //
  2206. //------------------------------------------------------------------------------
  2207. bool CAIHandler::FindOrLoadTable(IScriptTable* pGlobalTable, const char* szTableName, SmartScriptTable& tableOut)
  2208. {
  2209.         if (pGlobalTable->GetValue(szTableName, tableOut))
  2210.                 return true;
  2211.  
  2212.         SmartScriptTable pAvailableTable;
  2213.         if (!pGlobalTable->GetValue("AVAILABLE", pAvailableTable))
  2214.         {
  2215.                 AIWarningID("<CAIHandler> ", "AVAILABLE table not found. Aborting loading table");
  2216.                 return false;
  2217.         }
  2218.  
  2219.         const char* szFileName = 0;
  2220.         if (!pAvailableTable->GetValue(szTableName, szFileName))
  2221.         {
  2222.                 SmartScriptTable pInternalTable;
  2223.                 if (!pGlobalTable->GetValue("INTERNAL", pInternalTable) ||
  2224.                     !pInternalTable->GetValue(szTableName, szFileName))
  2225.                 {
  2226.                         return false;
  2227.                 }
  2228.         }
  2229.  
  2230.         if (gEnv->pScriptSystem->ExecuteFile(szFileName, true, false))
  2231.         {
  2232.                 if (pGlobalTable->GetValue(szTableName, tableOut))
  2233.                         return true;
  2234.         }
  2235.  
  2236.         // could not load script for character
  2237.         AIWarningID("<CAIHandler> ", "can't load script for character [%s]. Entity %s", szFileName, m_pEntity->GetName());
  2238.  
  2239.         return false;
  2240. }
  2241.  
  2242. //
  2243. //------------------------------------------------------------------------------
  2244. void CAIHandler::OnDialogLoaded(struct ILipSync* pLipSync)
  2245. {
  2246. }
  2247.  
  2248. //
  2249. //----------------------------------------------------------------------------------------------------------
  2250. void CAIHandler::OnDialogFailed(struct ILipSync* pLipSync)
  2251. {
  2252. }
  2253.  
  2254. //
  2255. //----------------------------------------------------------------------------------------------------------
  2256. void CAIHandler::Serialize(TSerialize ser)
  2257. {
  2258. #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM
  2259.         ser.Value("m_sCharacterName", m_sCharacterName);
  2260. #endif
  2261.         // Must be serialized before the character/behavior is set below.
  2262.         ser.Value("m_CurrentAlertness", m_CurrentAlertness);
  2263. #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM
  2264.         ser.Value("m_bDelayedCharacterConstructor", m_bDelayedCharacterConstructor);
  2265. #endif
  2266.         ser.Value("m_bDelayedBehaviorConstructor", m_bDelayedBehaviorConstructor);
  2267.         ser.Value("m_CurrentExclusive", m_CurrentExclusive);
  2268.         ser.Value("m_bSoundFinished", m_bSoundFinished);
  2269.         ser.Value("m_timeSinceEvent", m_timeSinceEvent);
  2270.         ser.Value("m_lastTargetID", m_lastTargetID);
  2271.         ser.Value("m_lastTargetPos", m_lastTargetPos);
  2272.  
  2273.         if (ser.IsReading())
  2274.         {
  2275.                 m_lastTargetThreat = AITHREAT_NONE;
  2276.                 m_lastTargetType = AITARGET_NONE;
  2277.         }
  2278.  
  2279.         // serialize behavior
  2280.         if (ser.IsReading())
  2281.         {
  2282.                 SetInitialBehaviorAndCharacter();
  2283. #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM
  2284.                 SetCharacter(m_sCharacterName.c_str(), SET_ON_SERILIAZE);
  2285. #endif
  2286.         }
  2287.  
  2288.         SerializeScriptAI(ser);
  2289.  
  2290.         IAnimationGraphState* pAGState = GetAGState();
  2291.         if (ser.IsReading())
  2292.         {
  2293.                 // TODO: Serialize the face manager instead of calling Reset().
  2294.                 m_FaceManager.Reset();
  2295.  
  2296.                 ResetAnimationData();
  2297.                 m_changeActionInputQueryId = m_changeSignalInputQueryId = 0;
  2298.                 if (pAGState && !GetActionController())
  2299.                 {
  2300.                         pAGState->QueryChangeInput(GetAGInputName(AIAG_ACTION), &m_changeActionInputQueryId);
  2301.                         pAGState->QueryChangeInput(GetAGInputName(AIAG_SIGNAL), &m_changeSignalInputQueryId);
  2302.                 }
  2303.         }
  2304.  
  2305.         ser.EnumValue("m_eActorTargetPhase", m_eActorTargetPhase, eATP_None, eATP_Error);
  2306.         ser.Value("m_actorTargetId", m_actorTargetId);
  2307.         ser.Value("m_vAnimationTargetPosition", m_vAnimationTargetPosition);
  2308.         if (ser.IsReading())
  2309.         {
  2310.                 switch (m_eActorTargetPhase)
  2311.                 {
  2312.                 case eATP_Waiting:
  2313.                         // exact positioning animation has been requested but not started yet.
  2314.                         // since it isn't serialized in the animation graph we have to request it again
  2315.                         m_eActorTargetPhase = eATP_None;
  2316.                         m_actorTargetId = 0;
  2317.                         break;
  2318.                 case eATP_Starting:
  2319.                 case eATP_Started:
  2320.                 case eATP_Playing:
  2321.                         // exact positioning animation has been started and playing.
  2322.                         // since it isn't serialized in the animation graph we need to know when animations is done.
  2323.                         // TODO: try to find a better way to track the progress of animation.
  2324.                         // TODO: make this work with vehicles.
  2325.                         if (pAGState)
  2326.                         {
  2327.                                 if (GetActionController())
  2328.                                 {
  2329.                                         m_eActorTargetPhase = eATP_None;
  2330.                                         m_actorTargetId = 0;
  2331.                                 }
  2332.                                 else
  2333.                                 {
  2334.                                         m_curActorTargetEndQueryID = &m_actorTargetEndQueryID;
  2335.                                         pAGState->QueryLeaveState(
  2336.                                           m_curActorTargetEndQueryID);
  2337.                                 }
  2338.                         }
  2339.                         break;
  2340.                 }
  2341.         }
  2342. }
  2343.  
  2344. //
  2345. //------------------------------------------------------------------------------
  2346. void CAIHandler::SerializeScriptAI(TSerialize& ser)
  2347. {
  2348.         CHECK_SCRIPT_STACK;
  2349.  
  2350.         if (m_pScriptObject && m_pScriptObject->HaveValue("OnSaveAI") && m_pScriptObject->HaveValue("OnLoadAI"))
  2351.         {
  2352.                 SmartScriptTable persistTable(m_pScriptObject->GetScriptSystem());
  2353.                 if (ser.IsWriting())
  2354.                         Script::CallMethod(m_pScriptObject, "OnSaveAI", persistTable);
  2355.                 ser.Value("ScriptData", persistTable.GetPtr());
  2356.                 if (ser.IsReading())
  2357.                         Script::CallMethod(m_pScriptObject, "OnLoadAI", persistTable);
  2358.         }
  2359. }
  2360.  
  2361. //
  2362. //------------------------------------------------------------------------------
  2363. void CAIHandler::Update()
  2364. {
  2365.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  2366.  
  2367. #ifdef USE_DEPRECATED_AI_CHARACTER_SYSTEM
  2368.         if (m_bDelayedCharacterConstructor)
  2369.         {
  2370.                 CallCharacterConstructor();
  2371.                 m_bDelayedCharacterConstructor = false;
  2372.         }
  2373. #endif
  2374.  
  2375.         if (m_bDelayedBehaviorConstructor)
  2376.         {
  2377.                 CallBehaviorConstructor(0);
  2378.                 m_bDelayedBehaviorConstructor = false;
  2379.         }
  2380.  
  2381.         /*      if (m_sCharacterName.empty())
  2382.            {
  2383.             const char* szDefaultCharacter = GetInitialCharacterName();
  2384.             m_sFirstCharacterName = szDefaultCharacter;
  2385.             SetCharacter(szDefaultCharacter);
  2386.            }
  2387.  
  2388.            if (m_sBehaviorName.empty())
  2389.            {
  2390.             const char* szDefaultBehavior = GetInitialBehaviorName();
  2391.             m_sFirstBehaviorName = szDefaultBehavior;
  2392.             m_pScriptObject->SetValue("DefaultBehaviour", szDefaultBehavior);
  2393.             SetBehavior(szDefaultBehavior);
  2394.            }*/
  2395.  
  2396.         m_FaceManager.Update();
  2397. }
  2398.  
  2399. //
  2400. //------------------------------------------------------------------------------
  2401. void CAIHandler::MakeFace(CAIFaceManager::e_ExpressionEvent expression)
  2402. {
  2403.         m_FaceManager.SetExpression(expression);
  2404. }
  2405.  
  2406. //
  2407. //------------------------------------------------------------------------------
  2408. /*static*/ const char* CAIHandler::GetAGInputName(EAIAGInput input)
  2409. {
  2410.         switch (input)
  2411.         {
  2412.         case AIAG_SIGNAL:
  2413.                 return "Signal";
  2414.         case AIAG_ACTION:
  2415.                 return "Action";
  2416.         default:
  2417.                 {
  2418.                         CRY_ASSERT_MESSAGE(false, "Invalid input name");
  2419.                         return NULL;
  2420.                 }
  2421.         }
  2422. }
  2423.  
  2424. //
  2425. //------------------------------------------------------------------------------
  2426. void CAIHandler::DoReadibilityPackForAIObjectsOfType(unsigned short int nType, const char* szText, float fResponseDelay)
  2427. {
  2428.         IAIObject* pAI = m_pEntity->GetAI();
  2429.         if (!pAI || !pAI->IsEnabled())
  2430.         {
  2431.                 return;
  2432.         }
  2433.  
  2434.         IAIActor* pAIActor = pAI->CastToIAIActor();
  2435.         int groupId = pAI->GetGroupId();
  2436.         IAISystem* pAISystem = gEnv->pAISystem;
  2437.         int count = pAISystem->GetGroupCount(groupId, IAISystem::GROUP_ENABLED, nType);
  2438.         float nearestDist = FLT_MAX;
  2439.         IAIObject* nearestInGroup = 0;
  2440.  
  2441.         for (int i = 0; i < count; ++i)
  2442.         {
  2443.                 IAIObject* responder = pAISystem->GetGroupMember(groupId, i, IAISystem::GROUP_ENABLED, nType);
  2444.                 // Skip self and puppets without proxies
  2445.                 if (responder == pAI || !responder->GetProxy()) continue;
  2446.                 CAIProxy* proxy = (CAIProxy*)responder->GetProxy();
  2447.                 if (!proxy->GetAIHandler()) continue;
  2448.                 // Choose nearest
  2449.                 float d = Distance::Point_PointSq(pAI->GetPos(), responder->GetPos());
  2450.                 if (d < nearestDist)
  2451.                 {
  2452.                         nearestDist = d;
  2453.                         nearestInGroup = responder;
  2454.                 }
  2455.         }
  2456.         // Send response request.
  2457.         if (nearestInGroup)
  2458.         {
  2459.                 IAISignalExtraData* pData = pAISystem->CreateSignalExtraData();
  2460.                 pData->iValue = 0;                                                              // Default Priority.
  2461.                 pData->fValue = fResponseDelay > 0.0f ? fResponseDelay : cry_random(2.5f, 4.f); // Delay
  2462.                 pAISystem->SendSignal(SIGNALFILTER_READABILITYRESPONSE, 1, szText, nearestInGroup, pData);
  2463.         }
  2464. }
  2465.  
  2466. //
  2467. //------------------------------------------------------------------------------
  2468. void CAIHandler::OnAnimActionTriStateEnter(CAnimActionTriState* pActionTriState)
  2469. {
  2470.         if (CAnimActionExactPositioning::IsExactPositioningAction(pActionTriState))
  2471.                 return;
  2472.  
  2473.         CAnimActionAIAction* pAction = static_cast<CAnimActionAIAction*>(pActionTriState);
  2474.  
  2475.         string value = pAction->GetValue();
  2476.         if (pAction->GetType() == CAnimActionAIAction::EAT_Looping)
  2477.         {
  2478.                 m_currentActionAnimName = value;
  2479.                 m_playingActionAnimation = true;
  2480.         }
  2481.         else if (pAction->GetType() == CAnimActionAIAction::EAT_OneShot)
  2482.         {
  2483.                 m_currentSignalAnimName = value;
  2484.                 m_playingSignalAnimation = true;
  2485.         }
  2486. }
  2487.  
  2488. //
  2489. //------------------------------------------------------------------------------
  2490. void CAIHandler::OnAnimActionTriStateMiddle(CAnimActionTriState* pActionTriState)
  2491. {
  2492.         if (CAnimActionExactPositioning::IsExactPositioningAction(pActionTriState))
  2493.                 return;
  2494.  
  2495.         CAnimActionAIAction* pAction = static_cast<CAnimActionAIAction*>(pActionTriState);
  2496.  
  2497.         string value = pAction->GetValue();
  2498.         if (pAction->GetType() == CAnimActionAIAction::EAT_Looping)
  2499.         {
  2500.                 CRY_ASSERT(m_currentActionAnimName == value);
  2501.                 CRY_ASSERT(m_playingActionAnimation);
  2502.  
  2503.                 m_setStartedActionAnimations.insert(value);
  2504.                 if (m_sQueriedActionAnimation == value)
  2505.                         m_sQueriedActionAnimation.clear();
  2506.         }
  2507.         else if (pAction->GetType() == CAnimActionAIAction::EAT_OneShot)
  2508.         {
  2509.                 CRY_ASSERT(m_currentSignalAnimName == value);
  2510.                 CRY_ASSERT(m_playingSignalAnimation);
  2511.  
  2512.                 m_playingSignalAnimation = false;
  2513.                 m_bSignaledAnimationStarted = true;
  2514.         }
  2515. }
  2516.  
  2517. //
  2518. //------------------------------------------------------------------------------
  2519. void CAIHandler::OnAnimActionTriStateExit(CAnimActionTriState* pActionTriState)
  2520. {
  2521.         if (!CAnimActionExactPositioning::IsExactPositioningAction(pActionTriState))
  2522.         {
  2523.                 CAnimActionAIAction* pAction = static_cast<CAnimActionAIAction*>(pActionTriState);
  2524.  
  2525.                 string value = pAction->GetValue();
  2526.                 if (pAction->GetType() == CAnimActionAIAction::EAT_Looping)
  2527.                 {
  2528.                         if (m_currentActionAnimName == value)
  2529.                         {
  2530.                                 m_playingActionAnimation = false;
  2531.                                 m_currentActionAnimName.clear();
  2532.                         }
  2533.                 }
  2534.                 else if (pAction->GetType() == CAnimActionAIAction::EAT_OneShot)
  2535.                 {
  2536.                         m_setPlayedSignalAnimations.insert(value);
  2537.  
  2538.                         // TODO: Check out the special case where you select the same signal
  2539.                         // animation while it is still playing
  2540.                         if (m_sQueriedSignalAnimation == value)
  2541.                                 m_sQueriedSignalAnimation.clear();
  2542.  
  2543.                         if (m_currentSignalAnimName == value)
  2544.                         {
  2545.                                 m_bSignaledAnimationStarted = false;
  2546.                                 m_currentSignalAnimName.clear();
  2547.                         }
  2548.                 }
  2549.         }
  2550.  
  2551.         m_animActionTracker.Remove(pActionTriState);
  2552. }
  2553.  
  2554. //
  2555. //------------------------------------------------------------------------------
  2556. bool CAIHandler::SetMannequinAGInput(IActionController* pActionController, EAIAGInput input, const char* value, const bool isUrgent)
  2557. {
  2558.         const uint32 valueCRC = CCrc32::ComputeLowercase(value);
  2559.         const FragmentID fragmentID = pActionController->GetContext().controllerDef.m_fragmentIDs.Find(valueCRC);
  2560.  
  2561.         if (input == AIAG_ACTION)
  2562.         {
  2563.                 static const uint32 idleCRC = CCrc32::ComputeLowercase("idle");
  2564.                 const bool isIdleValue = (valueCRC == idleCRC);
  2565.                 if ((fragmentID != FRAGMENT_ID_INVALID) && !isIdleValue)
  2566.                 {
  2567.                         stl::member_find_and_erase(m_setStartedActionAnimations, m_sQueriedActionAnimation);
  2568.                         m_sQueriedActionAnimation = value;
  2569.                         CAnimActionAIAction* pAnimAction = new CAnimActionAIAction(isUrgent, fragmentID, *GetActor()->GetAnimatedCharacter(), CAnimActionAIAction::EAT_Looping, value, *this);
  2570.                         m_animActionTracker.Add(pAnimAction);
  2571.                         pActionController->Queue(*pAnimAction);
  2572.  
  2573.                         return true;
  2574.                 }
  2575.                 else
  2576.                 {
  2577.                         if (!isIdleValue)
  2578.                         {
  2579.                                 //if (IPipeUser* pPipeUser = CastToIPipeUserSafe(m_pEntity->GetAI()))
  2580.                                 //{
  2581.                                 //      string message = string::Format("I cannot play looping animation '%s'", value);
  2582.                                 //      AIQueueBubbleMessage("CAIHandler::SetAGInput AIAG_ACTION Invalid value", pPipeUser, message.c_str(), eBNS_Log|eBNS_Balloon);
  2583.                                 //}
  2584.                                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CAIHandler::SetAGInput: Unable to find looping animation '%s'", value);
  2585.                         }
  2586.  
  2587.                         // Do we really want to cancel the currently playing action here in case of invalid fragmentid?
  2588.                         if (m_animActionTracker.IsNotEmpty())
  2589.                         {
  2590.                                 stl::member_find_and_erase(m_setStartedActionAnimations, m_sQueriedActionAnimation);
  2591.                                 if (isUrgent)
  2592.                                         m_animActionTracker.ForceFinishAll();
  2593.                                 else
  2594.                                         m_animActionTracker.StopAll();
  2595.                         }
  2596.  
  2597.                         m_sQueriedActionAnimation.clear();
  2598.  
  2599.                         if (isIdleValue)
  2600.                         {
  2601.                                 FinishRunningAGActions();
  2602.                         }
  2603.  
  2604.                         return false;
  2605.                 }
  2606.         } // if ACTION
  2607.         else if (input == AIAG_SIGNAL)
  2608.         {
  2609.                 //if ( m_sQueriedSignalAnimation == value )
  2610.                 //{
  2611.                 //      // Really? Do we really want this?  Don't we want the signal to trigger the animation AGAIN?
  2612.                 //      return true;
  2613.                 //}
  2614.                 static const uint32 noneCRC = CCrc32::ComputeLowercase("none");
  2615.                 const bool isNoneValue = (valueCRC == noneCRC);
  2616.                 if ((fragmentID != FRAGMENT_ID_INVALID) && !isNoneValue)
  2617.                 {
  2618.                         stl::member_find_and_erase(m_setPlayedSignalAnimations, value);
  2619.                         m_sQueriedSignalAnimation = value;
  2620.  
  2621.                         CAnimActionAIAction* pAnimAction = new CAnimActionAIAction(isUrgent, fragmentID, *GetActor()->GetAnimatedCharacter(), CAnimActionAIAction::EAT_OneShot, value, *this);
  2622.                         m_animActionTracker.Add(pAnimAction);
  2623.                         pActionController->Queue(*pAnimAction);
  2624.  
  2625.                         return true;
  2626.                 }
  2627.                 else
  2628.                 {
  2629.                         if (!isNoneValue)
  2630.                         {
  2631.                                 //if ( IPipeUser* pPipeUser = CastToIPipeUserSafe( m_pEntity->GetAI() ) )
  2632.                                 //{
  2633.                                 //      string message = string::Format( "I cannot play looping animation '%s'", value );
  2634.                                 //      AIQueueBubbleMessage( "CAIHandler::SetAGInput AIAG_SIGNAL Invalid value", pPipeUser, message.c_str(), eBNS_Log|eBNS_Balloon );
  2635.                                 //}
  2636.                                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "CAIHandler::SetAGInput: Unable to find one-shot animation '%s'", value);
  2637.                         }
  2638.  
  2639.                         // Do we really want to cancel the currently playing action here when we have an invalid fragmentid
  2640.                         if (m_animActionTracker.IsNotEmpty())
  2641.                         {
  2642.                                 stl::member_find_and_erase(m_setPlayedSignalAnimations, m_sQueriedSignalAnimation);
  2643.                                 if (isUrgent)
  2644.                                         m_animActionTracker.ForceFinishAll();
  2645.                                 else
  2646.                                         m_animActionTracker.StopAll();
  2647.                         }
  2648.  
  2649.                         m_sQueriedSignalAnimation.clear();
  2650.  
  2651.                         return false;
  2652.                 }
  2653.         } // if SIGNAL
  2654.         else
  2655.         {
  2656.                 return false;
  2657.         }
  2658. }
  2659.  
  2660. //
  2661. //------------------------------------------------------------------------------
  2662. bool CAIHandler::ResetMannequinAGInput(EAIAGInput input)
  2663. {
  2664.         if (input == AIAG_ACTION)
  2665.         {
  2666.                 if (m_animActionTracker.IsNotEmpty())
  2667.                 {
  2668.                         stl::member_find_and_erase(m_setStartedActionAnimations, m_sQueriedActionAnimation);   // wasn't this missing in the normal implementation?
  2669.                         m_animActionTracker.StopAllActionsOfType(false /*Looping*/);
  2670.                 }
  2671.         }
  2672.         else if (input == AIAG_SIGNAL)
  2673.         {
  2674.                 if (m_animActionTracker.IsNotEmpty())
  2675.                 {
  2676.                         stl::member_find_and_erase(m_setStartedActionAnimations, m_sQueriedActionAnimation);   // wasn't this missing in the normal implementation?
  2677.                         m_animActionTracker.StopAllActionsOfType(true /*OneShot*/);
  2678.                 }
  2679.         }
  2680.  
  2681.         // What about the other inputs?
  2682.  
  2683.         return true;
  2684. }
  2685.  
  2686. //
  2687. //------------------------------------------------------------------------------
  2688. void CAIHandler::FinishRunningAGActions()
  2689. {
  2690.         IAnimationGraphState* pAGState = GetAGState();
  2691.         if (pAGState)
  2692.                 pAGState->SetInput(GetAGInputName(AIAG_ACTION), "idle");
  2693. }
  2694.  
  2695. //
  2696. //------------------------------------------------------------------------------
  2697. void CAIHandler::SAnimActionTracker::ReleaseAll()
  2698. {
  2699.         TAnimActionVector::iterator itEnd = m_animActions.end();
  2700.         for (TAnimActionVector::iterator it = m_animActions.begin(); it != itEnd; ++it)
  2701.         {
  2702.                 AnimActionPtr& animAction = *it;
  2703.                 animAction->UnregisterListener();
  2704.                 if (animAction->GetStatus() != IAction::None)
  2705.                         animAction->ForceFinish();
  2706.         }
  2707.         m_animActions.clear();
  2708. }
  2709.  
  2710. //
  2711. //------------------------------------------------------------------------------
  2712. void CAIHandler::SAnimActionTracker::ForceFinishAll()
  2713. {
  2714.         for (TAnimActionVector::iterator it = m_animActions.begin(); it != m_animActions.end(); )
  2715.         {
  2716.                 AnimActionPtr& animAction = *it;
  2717.                 if (animAction->GetStatus() == IAction::None)
  2718.                 {
  2719.                         // let go of action as the exit callback won't get called
  2720.                         it = m_animActions.erase(it);
  2721.                 }
  2722.                 else if (animAction->GetStatus() == IAction::Pending)
  2723.                 {
  2724.                         // let go of action as the exit callback won't get called
  2725.                         it = m_animActions.erase(it);
  2726.                         animAction->ForceFinish();
  2727.                 }
  2728.                 else
  2729.                 {
  2730.                         animAction->ForceFinish();
  2731.                         ++it;
  2732.                 }
  2733.         }
  2734. }
  2735.  
  2736. //
  2737. //------------------------------------------------------------------------------
  2738. void CAIHandler::SAnimActionTracker::StopAll()
  2739. {
  2740.         for (TAnimActionVector::iterator it = m_animActions.begin(); it != m_animActions.end(); )
  2741.         {
  2742.                 AnimActionPtr& animAction = *it;
  2743.                 if (animAction->GetStatus() == IAction::None)
  2744.                 {
  2745.                         // let go of action as the exit callback won't get called
  2746.                         it = m_animActions.erase(it);
  2747.                 }
  2748.                 else if (animAction->GetStatus() == IAction::Pending)
  2749.                 {
  2750.                         // let go of action as the exit callback won't get called
  2751.                         it = m_animActions.erase(it);
  2752.                         animAction->Stop();
  2753.                 }
  2754.                 else
  2755.                 {
  2756.                         animAction->Stop();
  2757.                         ++it;
  2758.                 }
  2759.         }
  2760. }
  2761.  
  2762. //
  2763. //------------------------------------------------------------------------------
  2764. void CAIHandler::SAnimActionTracker::StopAllActionsOfType(bool isOneShot)
  2765. {
  2766.         for (TAnimActionVector::iterator it = m_animActions.begin(); it != m_animActions.end(); )
  2767.         {
  2768.                 AnimActionPtr& animAction = *it;
  2769.                 if (animAction->IsOneShot() == isOneShot)
  2770.                 {
  2771.                         if (animAction->GetStatus() == IAction::None)
  2772.                         {
  2773.                                 // let go of action as the exit callback won't get called
  2774.                                 it = m_animActions.erase(it);
  2775.                         }
  2776.                         else if (animAction->GetStatus() == IAction::Pending)
  2777.                         {
  2778.                                 // let go of action as the exit callback won't get called
  2779.                                 it = m_animActions.erase(it);
  2780.                                 animAction->Stop();
  2781.                         }
  2782.                         else
  2783.                         {
  2784.                                 animAction->Stop();
  2785.                                 ++it;
  2786.                         }
  2787.                 }
  2788.                 else
  2789.                 {
  2790.                         ++it;
  2791.                 }
  2792.         }
  2793. }
  2794.  
  2795. //
  2796. //------------------------------------------------------------------------------
  2797. void CAIHandler::SAnimActionTracker::Remove(CAnimActionTriState* pAction)
  2798. {
  2799.         TAnimActionVector::iterator itEnd = m_animActions.end();
  2800.         for (TAnimActionVector::iterator it = m_animActions.begin(); it != itEnd; ++it)
  2801.         {
  2802.                 AnimActionPtr& animAction = *it;
  2803.                 if (animAction.get() == pAction)
  2804.                 {
  2805.                         m_animActions.erase(it);
  2806.                         break;
  2807.                 }
  2808.         }
  2809. }
  2810.  
  2811. //
  2812. //------------------------------------------------------------------------------
  2813. void CAIHandler::SAnimActionTracker::Add(CAnimActionTriState* pAction)
  2814. {
  2815.         m_animActions.push_back(AnimActionPtr(pAction));
  2816. }
  2817.  
downloadAIHandler.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