BVB Source Codes

CRYENGINE Show AIActor.cpp Source code

Return Download CRYENGINE: download AIActor.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #include "StdAfx.h"
  4. #include "AIActor.h"
  5. #include "PipeUser.h"
  6. #include "GoalOp.h"
  7. #include "SelectionTree/SelectionTreeManager.h"
  8. #include <CryAISystem/BehaviorTree/IBehaviorTree.h>
  9. #include <CryAISystem/BehaviorTree/Node.h>
  10. #include <CryAISystem/BehaviorTree/XmlLoader.h>
  11. #include "BehaviorTree/BehaviorTreeNodes_AI.h"
  12. #include "TargetSelection/TargetTrackManager.h"
  13. #include "Navigation/NavigationSystem/NavigationSystem.h"
  14. #include "Group/GroupManager.h"
  15. #include "Factions/FactionMap.h"
  16. #include <CryCore/CryCrc32.h>
  17. #include <CryEntitySystem/IEntity.h>
  18.  
  19. #include <CryAISystem/VisionMapTypes.h>
  20. #include "SelectionTree/SelectionTreeDebugger.h"
  21. #include <limits>
  22.  
  23. #define GET_READY_TO_CHANGE_BEHAVIOR_SIGNAL "OnBehaviorChangeRequest"
  24.  
  25. //#pragma optimize("", off)
  26. //#pragma inline_depth(0)
  27.  
  28. static const float UNINITIALIZED_COS_CACHE = 2.0f;
  29.  
  30. //////////////////////////////////////////////////////////////////////
  31. // Construction/Destruction
  32. //////////////////////////////////////////////////////////////////////
  33.  
  34. #define _ser_value_(val) ser.Value( # val, val)
  35.  
  36. #pragma warning (disable : 4355)
  37. CAIActor::CAIActor()
  38.         : m_bCheckedBody(true)
  39. #ifdef CRYAISYSTEM_DEBUG
  40.         ,m_healthHistory(0)
  41. #endif
  42.         , m_lightLevel(AILL_LIGHT)
  43.         , m_usingCombatLight(false)
  44.         , m_perceptionDisabled(0)
  45.         , m_cachedWaterOcclusionValue(0.0f)
  46.         , m_vLastFullUpdatePos(ZERO)
  47.         , m_lastFullUpdateStance(STANCE_NULL)
  48.         , m_observer(false)
  49.         , m_bCloseContact(false)
  50.         , m_FOVPrimaryCos(UNINITIALIZED_COS_CACHE)
  51.         , m_FOVSecondaryCos(UNINITIALIZED_COS_CACHE)
  52.         , m_territoryShape(0)
  53.         , m_lastBodyDir(ZERO)
  54.         , m_bodyTurningSpeed(0)
  55.         , m_stimulusStartTime(-100.f)
  56.         , m_activeCoordinationCount(0)
  57.         , m_navigationTypeID(0)
  58.         , m_behaviorTreeEvaluationMode(EvaluateWhenVariablesChange)
  59.         , m_currentCollisionAvoidanceRadiusIncrement(0.0f)
  60.         , m_runningBehaviorTree(false)
  61. {
  62.         _fastcast_CAIActor = true;
  63.  
  64.         AILogComment("CAIActor (%p)", this);
  65. }
  66. #pragma warning (default : 4355)
  67.  
  68. CAIActor::~CAIActor()
  69. {
  70.         StopBehaviorTree();
  71.  
  72.         AILogComment("~CAIActor  %s (%p)", GetName(), this);
  73.  
  74.         gAIEnv.pGroupManager->RemoveGroupMember(GetGroupId(), GetAIObjectID());
  75.  
  76.         CAISystem* pAISystem = GetAISystem();
  77.  
  78.         CAIGroup* pGroup = pAISystem->GetAIGroup(GetGroupId());
  79.         if (pGroup)
  80.                 pGroup->RemoveMember(this);
  81.  
  82.         SetObserver(false);
  83.  
  84. #ifdef CRYAISYSTEM_DEBUG
  85.         delete m_healthHistory;
  86. #endif
  87.  
  88.         m_State.ClearSignals();
  89.  
  90.         pAISystem->NotifyEnableState(this, false);
  91.         pAISystem->UnregisterAIActor(StaticCast<CAIActor>(GetSelfReference()));
  92. }
  93.  
  94. void CAIActor::SetBehaviorVariable(const char* variableName, bool value)
  95. {
  96.         if (m_behaviorSelectionTree.get())
  97.         {
  98.                 SelectionVariableID variableID =
  99.                   m_behaviorSelectionTree->GetTemplate().GetVariableDeclarations().GetVariableID(variableName);
  100.                 assert(m_behaviorSelectionTree->GetTemplate().GetVariableDeclarations().IsDeclared(variableID));
  101. #ifndef _RELEASE
  102.                 if (!m_behaviorSelectionTree->GetTemplate().GetVariableDeclarations().IsDeclared(variableID))
  103.                 {
  104.                         CryWarning(VALIDATOR_MODULE_AI, VALIDATOR_WARNING, "Variable \"%s\" missing from %s's Behaviour Selection Tree.", variableName, GetName());
  105.                 }
  106. #endif
  107.                 m_behaviorSelectionVariables->SetVariable(variableID, value);
  108.         }
  109.  
  110.         {
  111.                 Variables::Collection* variableCollection = GetAISystem()->GetIBehaviorTreeManager()->GetBehaviorVariableCollection_Deprecated(GetEntityID());
  112.                 const Variables::Declarations* variableDeclarations = GetAISystem()->GetIBehaviorTreeManager()->GetBehaviorVariableDeclarations_Deprecated(GetEntityID());
  113.                 if (!variableCollection || !variableDeclarations)
  114.                         return;
  115.  
  116.                 Variables::VariableID variableID = Variables::GetVariableID(variableName);
  117.  
  118.                 if (variableDeclarations->IsDeclared(variableID))
  119.                         variableCollection->SetVariable(variableID, value);
  120.                 else
  121.                         AIWarning("Variable '%s' missing from %s's Behavior Tree.", variableName, GetName());
  122.         }
  123. }
  124.  
  125. bool CAIActor::GetBehaviorVariable(const char* variableName) const
  126. {
  127.         bool value = false;
  128.  
  129.         if (m_behaviorSelectionTree.get())
  130.         {
  131.                 SelectionVariableID variableID =
  132.                   m_behaviorSelectionTree->GetTemplate().GetVariableDeclarations().GetVariableID(variableName);
  133.  
  134.                 m_behaviorSelectionVariables->GetVariable(variableID, &value);
  135.                 return value;
  136.         }
  137.  
  138.         {
  139.                 Variables::Collection* variableCollection = GetAISystem()->GetIBehaviorTreeManager()->GetBehaviorVariableCollection_Deprecated(GetEntityID());
  140.                 const Variables::Declarations* variableDeclarations = GetAISystem()->GetIBehaviorTreeManager()->GetBehaviorVariableDeclarations_Deprecated(GetEntityID());
  141.                 if (!variableCollection || !variableDeclarations)
  142.                         return false;
  143.  
  144.                 Variables::VariableID variableID = Variables::GetVariableID(variableName);
  145.  
  146.                 if (variableDeclarations->IsDeclared(variableID))
  147.                         variableCollection->GetVariable(variableID, &value);
  148.                 else
  149.                         AIWarning("Variable '%s' missing from %s's Behavior Tree.", variableName, GetName());
  150.  
  151.                 return value;
  152.         }
  153. }
  154.  
  155. SelectionTree* CAIActor::GetBehaviorSelectionTree() const
  156. {
  157.         return m_behaviorSelectionTree.get();
  158. }
  159.  
  160. SelectionVariables* CAIActor::GetBehaviorSelectionVariables() const
  161. {
  162.         return m_behaviorSelectionVariables.get();
  163. }
  164.  
  165. void CAIActor::ResetModularBehaviorTree(EObjectResetType type)
  166. {
  167.         if (type == AIOBJRESET_SHUTDOWN)
  168.         {
  169.                 StopBehaviorTree();
  170.         }
  171.         else
  172.         {
  173.                 if (!m_modularBehaviorTreeName.empty())
  174.                 {
  175.                         StartBehaviorTree(m_modularBehaviorTreeName.c_str());
  176.                 }
  177.                 else
  178.                 {
  179.                         // Try to load a Modular Behavior Tree
  180.                         if (IScriptTable* table = GetEntity()->GetScriptTable())
  181.                         {
  182.                                 SmartScriptTable properties;
  183.                                 if (table->GetValue("Properties", properties) && properties)
  184.                                 {
  185.                                         const char* behaviorTreeName = NULL;
  186.  
  187.                                         if (properties->GetValue("esModularBehaviorTree", behaviorTreeName) && behaviorTreeName && behaviorTreeName[0])
  188.                                         {
  189.                                                 MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "Modular Behavior Tree Runtime");
  190.  
  191.                                                 StartBehaviorTree(behaviorTreeName);
  192.                                         }
  193.                                 }
  194.                         }
  195.                 }
  196.         }
  197. }
  198.  
  199. void CAIActor::ResetBehaviorSelectionTree(EObjectResetType type)
  200. {
  201.         m_behaviorTreeEvaluationMode = EvaluateWhenVariablesChange;
  202.  
  203.         bool bRemoveBehaviorSelectionTree = (type == AIOBJRESET_SHUTDOWN);
  204.         IAIActorProxy* proxy = GetProxy();
  205.  
  206.         if (!bRemoveBehaviorSelectionTree && proxy)
  207.         {
  208.                 // Try to load a Selection Tree
  209.                 const char* behaviorSelectionTreeName = proxy->GetBehaviorSelectionTreeName();
  210.  
  211.                 MEMSTAT_CONTEXT_FMT(EMemStatContextTypes::MSC_Other, 0, "Behavior Selection Tree: %s", behaviorSelectionTreeName);
  212.  
  213.                 bool treeChanged = ((behaviorSelectionTreeName && !m_behaviorSelectionTree.get()) ||
  214.                                     (behaviorSelectionTreeName != 0 && stricmp(m_behaviorSelectionTree->GetTemplate().GetName(), behaviorSelectionTreeName)));
  215.  
  216.                 if (treeChanged)
  217.                 {
  218.                         SelectionTreeTemplateID templateID = gAIEnv.pSelectionTreeManager->GetTreeTemplateID(behaviorSelectionTreeName);
  219.  
  220.                         if (gAIEnv.pSelectionTreeManager->HasTreeTemplate(templateID))
  221.                         {
  222.                                 const SelectionTreeTemplate& treeTemplate = gAIEnv.pSelectionTreeManager->GetTreeTemplate(templateID);
  223.                                 if (treeTemplate.Valid())
  224.                                 {
  225.                                         m_behaviorSelectionTree.reset(new SelectionTree(treeTemplate.GetSelectionTree()));
  226.                                         m_behaviorSelectionVariables.reset(new SelectionVariables(treeTemplate.GetVariableDeclarations().GetDefaults()));
  227.                                         m_behaviorSelectionVariables->ResetChanged(true);
  228.                                 }
  229.                         }
  230.                         else
  231.                         {
  232.                                 bRemoveBehaviorSelectionTree = true;
  233.                         }
  234.                 }
  235.         }
  236.  
  237.         if (bRemoveBehaviorSelectionTree)
  238.         {
  239.                 m_behaviorSelectionTree.reset();
  240.                 m_behaviorSelectionVariables.reset();
  241.         }
  242. }
  243.  
  244. bool CAIActor::ProcessBehaviorSelectionTreeSignal(const char* signalName, uint32 signalCRC)
  245. {
  246.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  247.  
  248.         if (m_behaviorSelectionVariables.get())
  249.         {
  250. #if defined(CRYAISYSTEM_DEBUG)
  251.                 m_behaviorSelectionVariables->DebugTrackSignalHistory(signalName);
  252. #endif
  253.  
  254.                 const SelectionTreeTemplate& treeTemplate = m_behaviorSelectionTree->GetTemplate();
  255.                 return treeTemplate.GetSignalVariables().ProcessSignal(signalName, signalCRC, *m_behaviorSelectionVariables);
  256.         }
  257.  
  258.         return false;
  259. }
  260.  
  261. bool CAIActor::UpdateBehaviorSelectionTree()
  262. {
  263.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  264.  
  265.         if (m_behaviorSelectionTree.get())
  266.         {
  267.                 const bool evaluateTree =
  268.                   m_behaviorSelectionVariables.get() &&
  269.                   m_behaviorSelectionVariables->Changed() &&
  270.                   m_behaviorTreeEvaluationMode == EvaluateWhenVariablesChange;
  271.  
  272.                 if (evaluateTree)
  273.                 {
  274.                         const char* behaviorName = "";
  275.  
  276.                         SelectionNodeID currentNodeID = m_behaviorSelectionTree->GetCurrentNodeID();
  277.                         BST_DEBUG_START_EVAL(this, *m_behaviorSelectionTree.get(), *m_behaviorSelectionVariables.get());
  278.                         SelectionNodeID selectedNodeID = m_behaviorSelectionTree->Evaluate(*m_behaviorSelectionVariables.get());
  279.                         BST_DEBUG_END_EVAL(this, selectedNodeID);
  280.                         if (selectedNodeID)
  281.                         {
  282.                                 m_behaviorSelectionVariables->ResetChanged();
  283.  
  284.                                 if (currentNodeID == selectedNodeID)
  285.                                         return false;
  286.  
  287.                                 const SelectionTreeNode& node = m_behaviorSelectionTree->GetNode(selectedNodeID);
  288.                                 behaviorName = node.GetName();
  289.  
  290.                                 const SelectionTreeTemplate& treeTemplate = m_behaviorSelectionTree->GetTemplate();
  291.                                 if (const char* translatedName = treeTemplate.GetTranslator().GetTranslation(selectedNodeID))
  292.                                         behaviorName = translatedName;
  293.                         }
  294.  
  295.                         IAIActorProxy* pProxy = GetProxy();
  296.                         assert(pProxy);
  297.                         if (pProxy)
  298.                                 pProxy->SetBehaviour(behaviorName);
  299.  
  300.                         return true;
  301.                 }
  302.         }
  303.  
  304.         return false;
  305. }
  306.  
  307. #if defined(CRYAISYSTEM_DEBUG)
  308.  
  309. void CAIActor::DebugDrawBehaviorSelectionTree()
  310. {
  311.         if (m_behaviorSelectionVariables.get())
  312.         {
  313.                 const SelectionTreeTemplate& treeTemplate = m_behaviorSelectionTree->GetTemplate();
  314.                 m_behaviorSelectionVariables->DebugDraw(true, treeTemplate.GetVariableDeclarations());
  315.         }
  316.  
  317.         if (m_behaviorSelectionTree.get())
  318.                 m_behaviorSelectionTree->DebugDraw();
  319. }
  320.  
  321. #endif
  322.  
  323. const SAIBodyInfo& CAIActor::QueryBodyInfo()
  324. {
  325.         m_proxy->QueryBodyInfo(m_bodyInfo);
  326.         return m_bodyInfo;
  327. }
  328.  
  329. const SAIBodyInfo& CAIActor::GetBodyInfo() const
  330. {
  331.         return m_bodyInfo;
  332. }
  333.  
  334. void CAIActor::SetPos(const Vec3& pos, const Vec3& dirFwrd)
  335. {
  336.         gAIEnv.pActorLookUp->Prepare(0);
  337.  
  338.         Vec3 position(pos);
  339.         Vec3 vEyeDir(dirFwrd);
  340.  
  341.         if (IAIActorProxy* pProxy = GetProxy())
  342.         {
  343.                 SAIBodyInfo bodyInfo;
  344.                 pProxy->QueryBodyInfo(bodyInfo);
  345.  
  346.                 assert(bodyInfo.vEyeDir.IsValid());
  347.                 assert(bodyInfo.vEyePos.IsValid());
  348.                 assert(bodyInfo.vFireDir.IsValid());
  349.                 assert(bodyInfo.vFirePos.IsValid());
  350.  
  351.                 position = bodyInfo.vEyePos;
  352.                 vEyeDir = bodyInfo.GetEyeDir();
  353.                 assert(vEyeDir.IsUnit());
  354.  
  355.                 SetViewDir(vEyeDir);
  356.                 SetBodyDir(bodyInfo.GetBodyDir());
  357.  
  358.                 SetFirePos(bodyInfo.vFirePos);
  359.                 SetFireDir(bodyInfo.vFireDir);
  360.                 SetMoveDir(bodyInfo.vMoveDir);
  361.                 SetEntityDir(bodyInfo.GetBodyDir());
  362.  
  363.                 assert(bodyInfo.vFireDir.IsUnit());
  364.                 assert(bodyInfo.vMoveDir.IsUnit() || bodyInfo.vMoveDir.IsZero());
  365.                 assert(bodyInfo.vEntityDir.IsUnit() || bodyInfo.vEntityDir.IsZero());
  366.         }
  367.  
  368.         CAIObject::SetPos(position, vEyeDir); // can set something else than passed position
  369.  
  370.         if (m_pFormation)
  371.                 m_pFormation->Update();
  372.  
  373.         if (m_observer)
  374.         {
  375.                 ObserverParams observerParams;
  376.                 observerParams.eyePosition = position;
  377.                 observerParams.eyeDirection = vEyeDir;
  378.  
  379.                 gAIEnv.pVisionMap->ObserverChanged(GetVisionID(), observerParams, eChangedPosition | eChangedOrientation);
  380.         }
  381.  
  382.         gAIEnv.pActorLookUp->UpdatePosition(this, position);
  383. }
  384.  
  385. //
  386. //------------------------------------------------------------------------------------------------------------------------
  387. void CAIActor::Reset(EObjectResetType type)
  388. {
  389.         CAIObject::Reset(type);
  390.  
  391.         if (type == AIOBJRESET_INIT)
  392.         {
  393.                 m_initialPosition.pos = GetEntity()->GetPos();
  394.                 m_initialPosition.isValid = true;
  395.         }
  396.  
  397.         m_bCheckedBody = true;
  398.  
  399.         CAISystem* pAISystem = GetAISystem();
  400.  
  401.         m_State.FullReset();
  402.  
  403.         // TODO : (MATT) Hack - move into the method {2007/10/30:21:01:16}
  404.         m_State.eLookStyle = LOOKSTYLE_DEFAULT;
  405.  
  406.         m_State.bAllowLowerBodyToTurn = true;
  407.  
  408.         ReleaseFormation();
  409.  
  410.         if (!m_proxy)
  411.         {
  412.                 AILogComment("CAIActor(%p) Creating AIActorProxy", this);
  413.                 m_proxy.reset(pAISystem->GetActorProxyFactory()->CreateActorProxy(GetEntityID()));
  414.                 gAIEnv.pActorLookUp->UpdateProxy(this);
  415.         }
  416.  
  417.         m_proxy->Reset(type);
  418.  
  419.         m_bEnabled = true;
  420.         m_bUpdatedOnce = false;
  421.  
  422. #ifdef AI_COMPILE_WITH_PERSONAL_LOG
  423.         m_personalLog.Clear();
  424. #endif
  425.  
  426. #ifdef CRYAISYSTEM_DEBUG
  427.         if (m_healthHistory)
  428.                 m_healthHistory->Reset();
  429. #endif
  430.  
  431.         // synch self with owner entity if there is one
  432.         IEntity* pEntity(GetEntity());
  433.         if (pEntity)
  434.         {
  435.                 m_bEnabled = pEntity->IsActive();
  436.                 SetPos(pEntity->GetPos());
  437.         }
  438.  
  439.         m_lightLevel = AILL_LIGHT;
  440.         m_usingCombatLight = false;
  441.         assert(m_perceptionDisabled == 0);
  442.         m_perceptionDisabled = 0;
  443.  
  444.         m_cachedWaterOcclusionValue = 0.0f;
  445.  
  446.         m_vLastFullUpdatePos.zero();
  447.         m_lastFullUpdateStance = STANCE_NULL;
  448.  
  449.         m_probableTargets.clear();
  450.  
  451.         m_blackBoard.Clear();
  452.         m_blackBoard.GetForScript()->SetValue("Owner", this->GetName());
  453.  
  454.         m_perceptionHandlerModifiers.clear();
  455.  
  456.         ResetPersonallyHostiles();
  457.         ResetBehaviorSelectionTree(type);
  458.  
  459.         ResetModularBehaviorTree(type);
  460.  
  461.         const char* navigationTypeName = m_proxy->GetNavigationTypeName();
  462.         if (navigationTypeName && *navigationTypeName)
  463.         {
  464.                 if (NavigationAgentTypeID id = gAIEnv.pNavigationSystem->GetAgentTypeID(navigationTypeName))
  465.                 {
  466.                         m_navigationTypeID = id;
  467.                 }
  468.         }
  469.  
  470.         pAISystem->NotifyEnableState(this, m_bEnabled && (type == AIOBJRESET_INIT));
  471.  
  472.         // Clear the W/T names we use for lookup
  473.         m_territoryShape = 0;
  474.         m_territoryShapeName.clear();
  475.  
  476.         m_lastBodyDir.zero();
  477.         m_bodyTurningSpeed = 0;
  478.  
  479.         if (GetType() != AIOBJECT_PLAYER)
  480.         {
  481.                 SetObserver(type == AIOBJRESET_INIT);
  482.                 SetObservable(type == AIOBJRESET_INIT);
  483.         }
  484.  
  485.         m_bCloseContact = false;
  486.         m_stimulusStartTime = -100.f;
  487.  
  488.         m_bodyInfo = SAIBodyInfo();
  489.  
  490.         m_activeCoordinationCount = 0;
  491.  
  492.         m_currentCollisionAvoidanceRadiusIncrement = 0.0f;
  493. }
  494.  
  495. void CAIActor::EnablePerception(bool enable)
  496. {
  497.         if (enable)
  498.                 --m_perceptionDisabled;
  499.         else
  500.                 ++m_perceptionDisabled;
  501.  
  502.         assert(m_perceptionDisabled >= 0); // Below zero? More disables then enables!
  503.         assert(m_perceptionDisabled < 16); // Just a little sanity check
  504. }
  505.  
  506. bool CAIActor::IsPerceptionEnabled() const
  507. {
  508.         return m_perceptionDisabled <= 0;
  509. }
  510.  
  511. void CAIActor::ResetPerception()
  512. {
  513.         m_probableTargets.clear();
  514. }
  515.  
  516. //
  517. //------------------------------------------------------------------------------------------------------------------------
  518. void CAIActor::ParseParameters(const AIObjectParams& params, bool bParseMovementParams)
  519. {
  520.         SetParameters(params.m_sParamStruct);
  521.  
  522.         if (bParseMovementParams)
  523.                 m_movementAbility = params.m_moveAbility;
  524.  
  525.         GetAISystem()->NotifyEnableState(this, m_bEnabled);
  526. }
  527.  
  528. //====================================================================
  529. // CAIObject::OnObjectRemoved
  530. //====================================================================
  531. void CAIActor::OnObjectRemoved(CAIObject* pObject)
  532. {
  533.         CAIObject::OnObjectRemoved(pObject);
  534.  
  535.         // make sure no pending signal left from removed AIObjects
  536.         if (!m_State.vSignals.empty())
  537.         {
  538.                 if (EntityId removedEntityID = pObject->GetEntityID())
  539.                 {
  540.                         DynArray<AISIGNAL>::iterator it = m_State.vSignals.begin();
  541.                         DynArray<AISIGNAL>::iterator end = m_State.vSignals.end();
  542.  
  543.                         for (; it != end; )
  544.                         {
  545.                                 AISIGNAL& curSignal = *it;
  546.  
  547.                                 if (curSignal.senderID == removedEntityID)
  548.                                 {
  549.                                         delete static_cast<AISignalExtraData*>(curSignal.pEData);
  550.                                         it = m_State.vSignals.erase(it);
  551.                                         end = m_State.vSignals.end();
  552.                                 }
  553.                                 else
  554.                                         ++it;
  555.                         }
  556.                 }
  557.         }
  558.  
  559.         for (unsigned i = 0; i < m_probableTargets.size(); )
  560.         {
  561.                 if (m_probableTargets[i] == pObject)
  562.                 {
  563.                         m_probableTargets[i] = m_probableTargets.back();
  564.                         m_probableTargets.pop_back();
  565.                 }
  566.                 else
  567.                         ++i;
  568.         }
  569.  
  570.         RemovePersonallyHostile(pObject->GetAIObjectID());
  571. }
  572.  
  573. //
  574. //------------------------------------------------------------------------------------------------------------------------
  575. void CAIActor::Update(EObjectUpdate type)
  576. {
  577.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  578.  
  579.         IAIActorProxy* pAIActorProxy = GetProxy();
  580.  
  581.         if (!CastToCPipeUser())
  582.         {
  583.                 if (!IsEnabled())
  584.                 {
  585.                         AIWarning("CAIActor::Update: Trying to update disabled AI Actor: %s", GetName());
  586.                         AIAssert(0);
  587.                         return;
  588.                 }
  589.  
  590.                 // There should never be AI Actors without proxies.
  591.                 if (!pAIActorProxy)
  592.                 {
  593.                         AIWarning("CAIActor::Update: AI Actor does not have proxy: %s", GetName());
  594.                         AIAssert(0);
  595.                         return;
  596.                 }
  597.                 // There should never be AI Actors without physics.
  598.                 if (!GetPhysics())
  599.                 {
  600.                         AIWarning("CAIActor::Update: AI Actor does not have physics: %s", GetName());
  601.                         AIAssert(0);
  602.                         return;
  603.                 }
  604.                 // dead AI Actors should never be updated
  605.                 if (pAIActorProxy->IsDead())
  606.                 {
  607.                         AIWarning("CAIActor::Update: Trying to update dead AI Actor: %s ", GetName());
  608.                         AIAssert(0);
  609.                         return;
  610.                 }
  611.         }
  612.  
  613.         QueryBodyInfo();
  614.  
  615.         UpdateBehaviorSelectionTree();
  616.         UpdateCloakScale();
  617.  
  618.         CAISystem* pAISystem = GetAISystem();
  619.  
  620.         // Determine if position has changed
  621.         const Vec3& vPos = GetPos();
  622.         if (type == AIUPDATE_FULL)
  623.         {
  624.                 if (!IsEquivalent(m_vLastFullUpdatePos, vPos, 1.f))
  625.                 {
  626.                         // Recalculate the water occlusion at the new point
  627.                         m_cachedWaterOcclusionValue = pAISystem->GetWaterOcclusionValue(vPos);
  628.  
  629.                         m_vLastFullUpdatePos = vPos;
  630.                         m_lastFullUpdateStance = m_bodyInfo.stance;
  631.                 }
  632.  
  633.                 // update close contact info
  634.                 if (m_bCloseContact && ((pAISystem->GetFrameStartTime() - m_CloseContactTime).GetMilliSecondsAsInt64() > 1500))
  635.                 {
  636.                         m_bCloseContact = false;
  637.                 }
  638.         }
  639.  
  640.         const float dt = pAISystem->GetFrameDeltaTime();
  641.         if (dt > 0.f)
  642.         {
  643.                 // Update body angle and body turn speed
  644.                 float turnAngle = Ang3::CreateRadZ(m_lastBodyDir, GetEntityDir());
  645.                 m_bodyTurningSpeed = turnAngle / dt;
  646.         }
  647.         else
  648.         {
  649.                 m_bodyTurningSpeed = 0;
  650.         }
  651.  
  652.         m_lastBodyDir = GetEntityDir();
  653.  
  654.         if (!CastToCPipeUser())
  655.         {
  656.                 if (type == AIUPDATE_FULL)
  657.                 {
  658.                         m_lightLevel = pAISystem->GetLightManager()->GetLightLevelAt(GetPos(), this, &m_usingCombatLight);
  659.                 }
  660.  
  661.                 // make sure to update direction when entity is not moved
  662.                 const SAIBodyInfo& bodyInfo = GetBodyInfo();
  663.                 SetPos(bodyInfo.vEyePos);
  664.                 SetEntityDir(bodyInfo.vEntityDir);
  665.                 SetBodyDir(bodyInfo.GetBodyDir());
  666.  
  667.                 // AI Actor goto stuff
  668.                 if (!m_State.vMoveTarget.IsZero())
  669.                 {
  670.                         Vec3 vToMoveTarget = m_State.vMoveTarget - GetPos();
  671.                         if (!m_movementAbility.b3DMove)
  672.                         {
  673.                                 vToMoveTarget.z = 0.f;
  674.                         }
  675.                         if (vToMoveTarget.GetLengthSquared() < sqr(m_movementAbility.pathRadius))
  676.                         {
  677.                                 ResetLookAt();
  678.                                 SetBodyTargetDir(bodyInfo.vEntityDir);
  679.                         }
  680.                         else
  681.                         {
  682.                                 SetBodyTargetDir(vToMoveTarget.GetNormalized());
  683.                         }
  684.                 }
  685.                 // End of AI Actor goto stuff
  686.  
  687.                 SetMoveDir(bodyInfo.vMoveDir);
  688.                 m_State.vMoveDir = bodyInfo.vMoveDir;
  689.  
  690.                 SetViewDir(bodyInfo.GetEyeDir());
  691.  
  692.                 CAIObject* pAttTarget = m_refAttentionTarget.GetAIObject();
  693.                 if (pAttTarget && pAttTarget->IsEnabled())
  694.                 {
  695.                         if (CanSee(pAttTarget->GetVisionID()))
  696.                         {
  697.                                 m_State.eTargetType = AITARGET_VISUAL;
  698.                                 m_State.nTargetType = pAttTarget->GetType();
  699.                                 m_State.bTargetEnabled = true;
  700.                         }
  701.                         else
  702.                         {
  703.                                 switch (m_State.eTargetType)
  704.                                 {
  705.                                 case AITARGET_VISUAL:
  706.                                         m_State.eTargetThreat = AITHREAT_AGGRESSIVE;
  707.                                         m_State.eTargetType = AITARGET_MEMORY;
  708.                                         m_State.nTargetType = pAttTarget->GetType();
  709.                                         m_State.bTargetEnabled = true;
  710.                                         m_stimulusStartTime = GetAISystem()->GetFrameStartTimeSeconds();
  711.                                         break;
  712.  
  713.                                 case AITARGET_MEMORY:
  714.                                 case AITARGET_SOUND:
  715.                                         if (GetAISystem()->GetFrameStartTimeSeconds() - m_stimulusStartTime >= 5.f)
  716.                                         {
  717.                                                 m_State.nTargetType = -1;
  718.                                                 m_State.bTargetEnabled = false;
  719.                                                 m_State.eTargetThreat = AITHREAT_NONE;
  720.                                                 m_State.eTargetType = AITARGET_NONE;
  721.  
  722.                                                 SetAttentionTarget(NILREF);
  723.                                         }
  724.                                         break;
  725.                                 }
  726.                         }
  727.                 }
  728.                 else
  729.                 {
  730.                         m_State.nTargetType = -1;
  731.                         m_State.bTargetEnabled = false;
  732.                         m_State.eTargetThreat = AITHREAT_NONE;
  733.                         m_State.eTargetType = AITARGET_NONE;
  734.  
  735.                         SetAttentionTarget(NILREF);
  736.                 }
  737.         }
  738.  
  739.         m_bUpdatedOnce = true;
  740. }
  741.  
  742. void CAIActor::UpdateProxy(EObjectUpdate type)
  743. {
  744.         IAIActorProxy* pAIActorProxy = GetProxy();
  745.  
  746.         SetMoveDir(m_State.vMoveDir);
  747.  
  748.         // Always update the AI proxy, also during dry updates. The Animation system
  749.         // needs correct and constantly updated predictions to correctly set animation
  750.         // parameters.
  751.         // (MATT) Try avoiding UpdateMind, which triggers script, signal and behaviour code, if only a dry update {2009/12/06}
  752.         assert(pAIActorProxy);
  753.         if (pAIActorProxy)
  754.                 pAIActorProxy->Update(m_State, (type == AIUPDATE_FULL));
  755. }
  756.  
  757. //
  758. //------------------------------------------------------------------------------------------------------------------------
  759. void CAIActor::UpdateCloakScale()
  760. {
  761.         m_Parameters.m_fCloakScale = m_Parameters.m_fCloakScaleTarget;
  762. }
  763.  
  764. //
  765. //------------------------------------------------------------------------------------------------------------------------
  766. void CAIActor::UpdateDisabled(EObjectUpdate type)
  767. {
  768.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  769.  
  770.         // (MATT) I'm assuming that AIActor should always have a proxy, or this could be bad for performance {2009/04/03}
  771.         IAIActorProxy* pProxy = GetProxy();
  772.         if (pProxy)
  773.                 pProxy->CheckUpdateStatus();
  774. }
  775.  
  776. //===================================================================
  777. // SetNavNodes
  778. //===================================================================
  779. void CAIActor::UpdateDamageParts(DamagePartVector& parts)
  780. {
  781.         IAIActorProxy* pProxy = GetProxy();
  782.         if (!pProxy)
  783.                 return;
  784.  
  785.         IPhysicalEntity* phys = pProxy->GetPhysics(true);
  786.         if (!phys)
  787.                 return;
  788.  
  789.         bool queryDamageValues = true;
  790.  
  791.         static ISurfaceTypeManager* pSurfaceMan = gEnv->p3DEngine->GetMaterialManager()->GetSurfaceTypeManager();
  792.  
  793.         pe_status_nparts statusNParts;
  794.         int nParts = phys->GetStatus(&statusNParts);
  795.  
  796.         if ((int)parts.size() != nParts)
  797.         {
  798.                 parts.resize(nParts);
  799.                 queryDamageValues = true;
  800.         }
  801.  
  802.         // The global damage table
  803.         SmartScriptTable pSinglePlayerTable;
  804.         SmartScriptTable pDamageTable;
  805.         if (queryDamageValues)
  806.         {
  807.                 gEnv->pScriptSystem->GetGlobalValue("SinglePlayer", pSinglePlayerTable);
  808.                 if (pSinglePlayerTable.GetPtr())
  809.                 {
  810.                         if (GetType() == AIOBJECT_PLAYER)
  811.                                 pSinglePlayerTable->GetValue("DamageAIToPlayer", pDamageTable);
  812.                         else
  813.                                 pSinglePlayerTable->GetValue("DamageAIToAI", pDamageTable);
  814.                 }
  815.                 if (!pDamageTable.GetPtr())
  816.                         queryDamageValues = false;
  817.         }
  818.  
  819.         pe_status_pos statusPos;
  820.         pe_params_part paramsPart;
  821.         for (statusPos.ipart = 0, paramsPart.ipart = 0; statusPos.ipart < nParts; ++statusPos.ipart, ++paramsPart.ipart)
  822.         {
  823.                 if (!phys->GetParams(&paramsPart) || !phys->GetStatus(&statusPos))
  824.                         continue;
  825.  
  826.                 primitives::box box;
  827.                 statusPos.pGeomProxy->GetBBox(&box);
  828.  
  829.                 box.center *= statusPos.scale;
  830.                 box.size *= statusPos.scale;
  831.  
  832.                 parts[statusPos.ipart].pos = statusPos.pos + statusPos.q * box.center;
  833.                 parts[statusPos.ipart].volume = (box.size.x * 2) * (box.size.y * 2) * (box.size.z * 2);
  834.  
  835.                 if (queryDamageValues)
  836.                 {
  837.                         const char* matName = 0;
  838.                         phys_geometry* pGeom = paramsPart.pPhysGeomProxy ? paramsPart.pPhysGeomProxy : paramsPart.pPhysGeom;
  839.                         if (pGeom->surface_idx >= 0 && pGeom->surface_idx < paramsPart.nMats)
  840.                         {
  841.                                 matName = pSurfaceMan->GetSurfaceType(pGeom->pMatMapping[pGeom->surface_idx])->GetName();
  842.                                 parts[statusPos.ipart].surfaceIdx = pGeom->surface_idx;
  843.                         }
  844.                         else
  845.                         {
  846.                                 parts[statusPos.ipart].surfaceIdx = -1;
  847.                         }
  848.                         float damage = 0.0f;
  849.                         // The this is a bit dodgy, but the keys in the damage table exclude the 'mat_' part of the material name.
  850.                         if (pDamageTable.GetPtr() && matName && strlen(matName) > 4)
  851.                                 pDamageTable->GetValue(matName + 4, damage);
  852.                         parts[statusPos.ipart].damageMult = damage;
  853.                 }
  854.         }
  855. }
  856.  
  857. void CAIActor::OnAIHandlerSentSignal(const char* signalText, uint32 crc)
  858. {
  859.         IF_UNLIKELY (crc == 0)
  860.         {
  861.                 crc = CCrc32::Compute(signalText);
  862.         }
  863.         else
  864.         {
  865.                 assert(crc == CCrc32::Compute(signalText));
  866.         }
  867.  
  868.         if (gAIEnv.CVars.LogSignals)
  869.                 gEnv->pLog->Log("OnAIHandlerSentSignal: '%s' [%s].", signalText, GetName());
  870.  
  871.         ProcessBehaviorSelectionTreeSignal(signalText, crc);
  872.  
  873.         if (IsRunningBehaviorTree())
  874.         {
  875.                 BehaviorTree::Event event(
  876.                   crc
  877. #ifdef USING_BEHAVIOR_TREE_EVENT_DEBUGGING
  878.                   , signalText
  879. #endif
  880.                   );
  881.  
  882.                 GetAISystem()->GetIBehaviorTreeManager()->HandleEvent(GetEntityID(), event);
  883.         }
  884. }
  885.  
  886. // nSignalID = 10 allow duplicating signals
  887. // nSignalID = 9 use the signal only to notify wait goal operations
  888. //
  889. //------------------------------------------------------------------------------------------------------------------------
  890. void CAIActor::SetSignal(int nSignalID, const char* szText, IEntity* pSender, IAISignalExtraData* pData, uint32 crcCode)
  891. {
  892.         CCCPOINT(SetSignal);
  893.  
  894.         // Ensure we delete the pData object if we early out
  895.         struct DeleteBeforeReturning
  896.         {
  897.                 IAISignalExtraData** _p;
  898.                 DeleteBeforeReturning(IAISignalExtraData** p) : _p(p) {}
  899.                 ~DeleteBeforeReturning()
  900.                 {
  901.                         if (*_p)
  902.                                 GetAISystem()->FreeSignalExtraData((AISignalExtraData*)*_p);
  903.                 }
  904.         } autoDelete(&pData);
  905.  
  906. #ifdef _DEBUG
  907.         if (strlen(szText) + 1 > sizeof(((AISIGNAL*)0)->strText))
  908.         {
  909.                 AIWarning("####>CAIObject::SetSignal SIGNAL STRING IS TOO LONG for <%s> :: %s  sz-> %" PRISIZE_T, GetName(), szText, strlen(szText));
  910.                 //              AILogEvent("####>CAIObject::SetSignal <%s> :: %s  sz-> %d",m_sName.c_str(),szText,strlen(szText));
  911.         }
  912. #endif // _DEBUG
  913.  
  914.         // always process signals sent only to notify wait goal operation
  915.         if (crcCode == 0)
  916.                 crcCode = CCrc32::Compute(szText);
  917.  
  918.         // (MATT) This is the only place that the CRCs are used and their implementation is very clumsy {2008/08/09}
  919.         if (nSignalID != AISIGNAL_NOTIFY_ONLY)
  920.         {
  921. #ifdef _DEBUG
  922.                 if (nSignalID != AISIGNAL_ALLOW_DUPLICATES)
  923.                 {
  924.                         DynArray<AISIGNAL>::iterator ai;
  925.                         for (ai = m_State.vSignals.begin(); ai != m_State.vSignals.end(); ++ai)
  926.                         {
  927.                                 //      if ((*ai).strText == szText)
  928.                                 //if (!stricmp((*ai).strText,szText))
  929.  
  930.                                 if (!stricmp((*ai).strText, szText) && !(*ai).Compare(crcCode))
  931.                                 {
  932.                                         AIWarning("Hash values are different, but strings are identical! %s - %s ", (*ai).strText, szText);
  933.                                 }
  934.  
  935.                                 if (stricmp((*ai).strText, szText) && (*ai).Compare(crcCode))
  936.                                 {
  937.                                         AIWarning("Please report to alexey@crytek.de! Hash values are identical, but strings are different! %s - %s ", (*ai).strText, szText);
  938.                                 }
  939.                         }
  940.                 }
  941. #endif // _DEBUG
  942.  
  943.                 if (!m_bEnabled && nSignalID != AISIGNAL_INCLUDE_DISABLED)
  944.                 {
  945.                         // (Kevin) This seems like an odd assumption to be making. INCLUDE_DISABLED needs to be a bit or a separate passed-in value.
  946.                         //      WarFace compatibility cannot have duplicate signals sent to disabled AI. (08/14/2009)
  947.                         if (gAIEnv.configuration.eCompatibilityMode == ECCM_WARFACE || nSignalID != AISIGNAL_ALLOW_DUPLICATES)
  948.                         {
  949.                                 AILogComment("AIActor %p %s dropped signal \'%s\' due to being disabled", this, GetName(), szText);
  950.                                 return;
  951.                         }
  952.                 }
  953.         }
  954.  
  955. #ifdef CRYAISYSTEM_DEBUG
  956.         if (nSignalID != AISIGNAL_RECEIVED_PREV_UPDATE)// received last update
  957.         {
  958.                 IAIRecordable::RecorderEventData recorderEventData(szText);
  959.                 RecordEvent(IAIRecordable::E_SIGNALRECIEVED, &recorderEventData);
  960.                 GetAISystem()->Record(this, IAIRecordable::E_SIGNALRECIEVED, szText);
  961.         }
  962. #endif
  963.  
  964.         // don't let notify signals enter the queue
  965.         if (nSignalID == AISIGNAL_NOTIFY_ONLY)
  966.         {
  967.                 OnAIHandlerSentSignal(szText, crcCode); // still a polymorphic call that ends up in the most derived class (which is intended)
  968.                 return;
  969.         }
  970.  
  971.         AISIGNAL signal;
  972.         signal.nSignal = nSignalID;
  973.         cry_strcpy(signal.strText, szText);
  974.         signal.m_nCrcText = crcCode;
  975.         signal.senderID = pSender ? pSender->GetId() : 0;
  976.         signal.pEData = pData;
  977.  
  978.         // If all our early-outs passed and it wasn't just a "notify" then actually enter the signal into the stack!
  979.  
  980.         // cppcheck-suppress uselessAssignmentPtrArg
  981.         pData = NULL; // set to NULL to prevent autodeletion of pData on return
  982.  
  983.         // need to make sure constructor signal is always at the back - to be processed first
  984.         if (!m_State.vSignals.empty())
  985.         {
  986.                 AISIGNAL backSignal(m_State.vSignals.back());
  987.  
  988.                 if (!stricmp("Constructor", backSignal.strText))
  989.                 {
  990.                         m_State.vSignals.pop_back();
  991.                         m_State.vSignals.push_back(signal);
  992.                         m_State.vSignals.push_back(backSignal);
  993.                 }
  994.                 else
  995.                         m_State.vSignals.push_back(signal);
  996.         }
  997.         else
  998.                 m_State.vSignals.push_back(signal);
  999. }
  1000.  
  1001. //====================================================================
  1002. // IsHostile
  1003. //====================================================================
  1004. bool CAIActor::IsHostile(const IAIObject* pOtherAI, bool bUsingAIIgnorePlayer) const
  1005. {
  1006.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  1007.  
  1008.         bool hostile = false;
  1009.  
  1010.         if (pOtherAI)
  1011.         {
  1012.                 const CAIObject* other = static_cast<const CAIObject*>(pOtherAI);
  1013.  
  1014.                 if (other->GetType() == AIOBJECT_ATTRIBUTE)
  1015.                 {
  1016.                         if (CAIObject* association = other->GetAssociation().GetAIObject())
  1017.                                 other = association;
  1018.                 }
  1019.  
  1020.                 if (bUsingAIIgnorePlayer && (other->GetType() == AIOBJECT_PLAYER) && (gAIEnv.CVars.IgnorePlayer != 0))
  1021.                         return false;
  1022.  
  1023.                 uint8 myFaction = GetFactionID();
  1024.                 uint8 otherFaction = other->GetFactionID();
  1025.  
  1026.                 if (!other->IsThreateningForHostileFactions())
  1027.                         return false;
  1028.  
  1029.                 hostile = (gAIEnv.pFactionMap->GetReaction(myFaction, otherFaction) == IFactionMap::Hostile);
  1030.  
  1031.                 if (!hostile && !m_forcefullyHostiles.empty())
  1032.                 {
  1033.                         if (m_forcefullyHostiles.find(pOtherAI->GetAIObjectID()) != m_forcefullyHostiles.end())
  1034.                                 hostile = true;
  1035.                 }
  1036.  
  1037.                 if (hostile)
  1038.                 {
  1039.                         if (const CAIActor* actor = other->CastToCAIActor())
  1040.                                 if (bUsingAIIgnorePlayer && (m_Parameters.m_bAiIgnoreFgNode || actor->GetParameters().m_bAiIgnoreFgNode))
  1041.                                         hostile = false;
  1042.                 }
  1043.         }
  1044.  
  1045.         return hostile;
  1046. }
  1047.  
  1048. //
  1049. //------------------------------------------------------------------------------------------------------------------------
  1050. void CAIActor::Event(unsigned short eType, SAIEVENT* pEvent)
  1051. {
  1052.         CAISystem* pAISystem = GetAISystem();
  1053.         IAIActorProxy* pAIActorProxy = GetProxy();
  1054.  
  1055.         bool bWasEnabled = m_bEnabled;
  1056.  
  1057.         CAIObject::Event(eType, pEvent);
  1058.  
  1059.         // Inspired by CPuppet::Event's switch [4/25/2010 evgeny]
  1060.         switch (eType)
  1061.         {
  1062.         case AIEVENT_DISABLE:
  1063.                 {
  1064.                         // Reset and disable the agent's target track
  1065.                         const tAIObjectID aiObjectId = GetAIObjectID();
  1066.                         gAIEnv.pTargetTrackManager->ResetAgent(aiObjectId);
  1067.                         gAIEnv.pTargetTrackManager->SetAgentEnabled(aiObjectId, false);
  1068.  
  1069.                         pAISystem->UpdateGroupStatus(GetGroupId());
  1070.                         pAISystem->NotifyEnableState(this, false);
  1071.  
  1072.                         SetObserver(false);
  1073.                 }
  1074.                 break;
  1075.         case AIEVENT_ENABLE:
  1076.                 if (pAIActorProxy->IsDead())
  1077.                 {
  1078.                         // can happen when rendering dead bodies? AI should not be enabled
  1079.                         //                              AIAssert(!"Trying to enable dead character!");
  1080.                         return;
  1081.                 }
  1082.                 m_bEnabled = true;
  1083.                 gAIEnv.pTargetTrackManager->SetAgentEnabled(GetAIObjectID(), true);
  1084.                 pAISystem->UpdateGroupStatus(GetGroupId());
  1085.                 pAISystem->NotifyEnableState(this, true);
  1086.  
  1087.                 SetObserver(GetType() != AIOBJECT_PLAYER);
  1088.                 SetObservable(true);
  1089.                 break;
  1090.         case AIEVENT_SLEEP:
  1091.                 m_bCheckedBody = false;
  1092.                 if (pAIActorProxy->GetLinkedVehicleEntityId() == 0)
  1093.                 {
  1094.                         m_bEnabled = false;
  1095.                         pAISystem->NotifyEnableState(this, m_bEnabled);
  1096.                 }
  1097.                 break;
  1098.         case AIEVENT_WAKEUP:
  1099.                 m_bEnabled = true;
  1100.                 pAISystem->NotifyEnableState(this, m_bEnabled);
  1101.                 m_bCheckedBody = true;
  1102.                 pAISystem->UpdateGroupStatus(GetGroupId());
  1103.                 break;
  1104.         case AIEVENT_ONVISUALSTIMULUS:
  1105.                 HandleVisualStimulus(pEvent);
  1106.                 break;
  1107.         case AIEVENT_ONSOUNDEVENT:
  1108.                 HandleSoundEvent(pEvent);
  1109.                 break;
  1110.         case AIEVENT_ONBULLETRAIN:
  1111.                 HandleBulletRain(pEvent);
  1112.                 break;
  1113.         case AIEVENT_AGENTDIED:
  1114.                 {
  1115.                         ResetModularBehaviorTree(AIOBJRESET_SHUTDOWN);
  1116.  
  1117.                         pAISystem->NotifyTargetDead(this);
  1118.  
  1119.                         m_bCheckedBody = false;
  1120.                         m_bEnabled = false;
  1121.                         pAISystem->NotifyEnableState(this, m_bEnabled);
  1122.  
  1123.                         pAISystem->RemoveFromGroup(GetGroupId(), this);
  1124.  
  1125.                         pAISystem->ReleaseFormationPoint(this);
  1126.                         CancelRequestedPath(false);
  1127.                         ReleaseFormation();
  1128.  
  1129.                         m_State.ClearSignals();
  1130.  
  1131.                         const EntityId killerID = pEvent->targetId;
  1132.                         pAISystem->OnAgentDeath(GetEntityID(), killerID);
  1133.  
  1134.                         if (pAIActorProxy)
  1135.                         {
  1136.                                 pAIActorProxy->Reset(AIOBJRESET_SHUTDOWN);
  1137.                         }
  1138.  
  1139.                         SetObservable(false);
  1140.                         SetObserver(false);
  1141.                 }
  1142.                 break;
  1143.         }
  1144.  
  1145.         // Update the group status
  1146.         if (bWasEnabled != m_bEnabled)
  1147.         {
  1148.                 GetAISystem()->UpdateGroupStatus(GetGroupId());
  1149.         }
  1150. }
  1151.  
  1152. void CAIActor::EntityEvent(const SEntityEvent& event)
  1153. {
  1154.         switch (event.event)
  1155.         {
  1156.         case ENTITY_EVENT_ATTACH_THIS:
  1157.         case ENTITY_EVENT_DETACH_THIS:
  1158.                 QueryBodyInfo();
  1159.                 break;
  1160.  
  1161.         case ENTITY_EVENT_ENABLE_PHYSICS:
  1162.                 UpdateObserverSkipList();
  1163.                 break;
  1164.  
  1165.         case ENTITY_EVENT_DONE:
  1166.                 StopBehaviorTree();
  1167.                 break;
  1168.  
  1169.         default:
  1170.                 break;
  1171.         }
  1172.  
  1173.         CAIObject::EntityEvent(event);
  1174. }
  1175.  
  1176. //====================================================================
  1177. //
  1178. //====================================================================
  1179. bool CAIActor::CanAcquireTarget(IAIObject* pOther) const
  1180. {
  1181.         if (!pOther || !pOther->IsEnabled() || pOther->GetEntity()->IsHidden())
  1182.                 return false;
  1183.  
  1184.         CCCPOINT(CAIActor_CanAcquireTarget);
  1185.  
  1186.         CAIObject* pOtherAI = (CAIObject*)pOther;
  1187.         if (pOtherAI->GetType() == AIOBJECT_ATTRIBUTE && pOtherAI->GetAssociation().IsValid())
  1188.                 pOtherAI = (CAIObject*)pOtherAI->GetAssociation().GetAIObject();
  1189.  
  1190.         if (!pOtherAI || !pOtherAI->IsTargetable())
  1191.                 return false;
  1192.  
  1193.         CAIActor* pOtherActor = pOtherAI->CastToCAIActor();
  1194.         if (!pOtherActor)
  1195.                 return (pOtherAI->GetType() == AIOBJECT_TARGET);
  1196.  
  1197.         if (GetAISystem()->GetCombatClassScale(m_Parameters.m_CombatClass, pOtherActor->GetParameters().m_CombatClass) > 0)
  1198.                 return true;
  1199.         return false;
  1200. }
  1201.  
  1202. //
  1203. //------------------------------------------------------------------------------------------------------------------------
  1204. void CAIActor::SetGroupId(int id)
  1205. {
  1206.         if (id != GetGroupId())
  1207.         {
  1208.                 gAIEnv.pGroupManager->RemoveGroupMember(GetGroupId(), GetAIObjectID());
  1209.                 if (id > 0)
  1210.                         gAIEnv.pGroupManager->AddGroupMember(id, GetAIObjectID());
  1211.  
  1212.                 CAIObject::SetGroupId(id);
  1213.                 GetAISystem()->AddToGroup(this);
  1214.  
  1215.                 CAIObject* pBeacon = (CAIObject*)GetAISystem()->GetBeacon(id);
  1216.                 if (pBeacon)
  1217.                         GetAISystem()->UpdateBeacon(id, pBeacon->GetPos(), this);
  1218.  
  1219.                 m_Parameters.m_nGroup = id;
  1220.         }
  1221. }
  1222.  
  1223. void CAIActor::SetFactionID(uint8 factionID)
  1224. {
  1225.         CAIObject::SetFactionID(factionID);
  1226.  
  1227.         if (IsObserver())
  1228.         {
  1229.                 ObserverParams params;
  1230.                 uint8 faction = GetFactionID();
  1231.                 params.factionsToObserveMask = GetFactionVisionMask(faction);
  1232.                 params.faction = faction;
  1233.  
  1234.                 gAIEnv.pVisionMap->ObserverChanged(GetVisionID(), params, eChangedFaction | eChangedFactionsToObserveMask);
  1235.         }
  1236. }
  1237.  
  1238. void CAIActor::RegisterBehaviorListener(IActorBehaviorListener* listener)
  1239. {
  1240.         m_behaviorListeners.insert(listener);
  1241. }
  1242.  
  1243. void CAIActor::UnregisterBehaviorListener(IActorBehaviorListener* listener)
  1244. {
  1245.         m_behaviorListeners.erase(listener);
  1246. }
  1247.  
  1248. void CAIActor::BehaviorEvent(EBehaviorEvent event)
  1249. {
  1250.         BehaviorListeners::iterator it = m_behaviorListeners.begin();
  1251.         BehaviorListeners::iterator end = m_behaviorListeners.end();
  1252.  
  1253.         for (; it != end; )
  1254.         {
  1255.                 BehaviorListeners::iterator next = it;
  1256.                 ++next;
  1257.  
  1258.                 IActorBehaviorListener* listener = *it;
  1259.                 listener->BehaviorEvent(this, event);
  1260.  
  1261.                 it = next;
  1262.         }
  1263. }
  1264.  
  1265. void CAIActor::BehaviorChanged(const char* current, const char* previous)
  1266. {
  1267.         BehaviorListeners::iterator it = m_behaviorListeners.begin();
  1268.         BehaviorListeners::iterator end = m_behaviorListeners.end();
  1269.  
  1270.         for (; it != end; )
  1271.         {
  1272.                 BehaviorListeners::iterator next = it;
  1273.                 ++next;
  1274.  
  1275.                 IActorBehaviorListener* listener = *it;
  1276.                 listener->BehaviorChanged(this, current, previous);
  1277.  
  1278.                 it = next;
  1279.         }
  1280. }
  1281.  
  1282. //
  1283. //------------------------------------------------------------------------------------------------------------------------
  1284. void CAIActor::SetParameters(const AgentParameters& sParams)
  1285. {
  1286.         SetGroupId(sParams.m_nGroup);
  1287.         SetFactionID(sParams.factionID);
  1288.  
  1289.         m_Parameters = sParams;
  1290.         m_Parameters.m_fAccuracy = clamp_tpl(m_Parameters.m_fAccuracy, 0.0f, 1.0f);
  1291.  
  1292.         GetAISystem()->AddToFaction(this, sParams.factionID);
  1293.  
  1294.         CacheFOVCos(sParams.m_PerceptionParams.FOVPrimary, sParams.m_PerceptionParams.FOVSecondary);
  1295.         float range = std::max<float>(sParams.m_PerceptionParams.sightRange,
  1296.                                       sParams.m_PerceptionParams.sightRangeVehicle);
  1297.  
  1298.         VisionChanged(range, m_FOVPrimaryCos, m_FOVSecondaryCos);
  1299. }
  1300.  
  1301. #ifdef CRYAISYSTEM_DEBUG
  1302. void CAIActor::UpdateHealthHistory()
  1303. {
  1304.         if (!GetProxy()) return;
  1305.         if (!m_healthHistory)
  1306.                 m_healthHistory = new CValueHistory<float>(100, 0.1f);
  1307.         //better add float functions here
  1308.         float health = (GetProxy()->GetActorHealth() + GetProxy()->GetActorArmor());
  1309.         float maxHealth = (float)GetProxy()->GetActorMaxHealth();
  1310.  
  1311.         m_healthHistory->Sample(health / maxHealth, GetAISystem()->GetFrameDeltaTime());
  1312. }
  1313. #endif
  1314.  
  1315. //
  1316. //------------------------------------------------------------------------------------------------------------------------
  1317. void CAIActor::Serialize(TSerialize ser)
  1318. {
  1319.         ser.Value("m_bCheckedBody", m_bCheckedBody);
  1320.  
  1321.         m_State.Serialize(ser);
  1322.         m_Parameters.Serialize(ser);
  1323.         SerializeMovementAbility(ser);
  1324.  
  1325.         CAIObject::Serialize(ser);
  1326.  
  1327.         if (ser.IsReading())
  1328.         {
  1329.                 SetParameters(m_Parameters);
  1330.         }
  1331.  
  1332.         if (ser.IsReading())
  1333.         {
  1334.                 const EntityId entityId = GetEntityID();
  1335.                 assert(entityId > 0);
  1336.  
  1337.                 // The proxy may already exist, if this actor is being created due to an entity
  1338.                 //      being prepared from the pool.
  1339.                 if (!m_proxy.get())
  1340.                 {
  1341.                         AILogComment("CAIActor(%p) Creating AIActorProxy for serialization.", this);
  1342.                         m_proxy.reset(GetAISystem()->GetActorProxyFactory()->CreateActorProxy(entityId));
  1343.                 }
  1344.  
  1345.                 gAIEnv.pActorLookUp->UpdateProxy(this);
  1346.         }
  1347.  
  1348.         assert(m_proxy != 0);
  1349.         if (m_proxy)
  1350.                 m_proxy->Serialize(ser);
  1351.         else
  1352.                 AIWarning("CAIActor::Serialize Missing proxy for \'%s\' after loading", GetName());
  1353.  
  1354.         assert((m_behaviorSelectionTree.get() != NULL) == (m_behaviorSelectionVariables.get() != NULL));
  1355.  
  1356.         ser.EnumValue("m_behaviorTreeEvaluationMode", m_behaviorTreeEvaluationMode, FirstBehaviorTreeEvaluationMode, BehaviorTreeEvaluationModeCount);
  1357.  
  1358.         if (ser.BeginOptionalGroup("BehaviorSelectionTree", m_behaviorSelectionTree.get() != NULL))
  1359.         {
  1360.                 if (ser.IsReading())
  1361.                         ResetBehaviorSelectionTree(AIOBJRESET_INIT);
  1362.  
  1363.                 assert(m_behaviorSelectionTree.get() != NULL);
  1364.                 assert(m_behaviorSelectionVariables.get() != NULL);
  1365.  
  1366.                 if (m_behaviorSelectionTree.get() != NULL)
  1367.                         m_behaviorSelectionTree->Serialize(ser);
  1368.                 else
  1369.                         AIWarning("CAIActor::Serialize Missing Behavior Selection Tree for \'%s\' after loading", GetName());
  1370.  
  1371.                 if (m_behaviorSelectionVariables.get() != NULL)
  1372.                         m_behaviorSelectionVariables->Serialize(ser);
  1373.                 else
  1374.                         AIWarning("CAIActor::Serialize Missing Behavior Selection Variables for \'%s\' after loading", GetName());
  1375.  
  1376.                 if (ser.IsReading())
  1377.                         UpdateBehaviorSelectionTree();
  1378.  
  1379.                 ser.EndGroup();
  1380.         }
  1381.         else if (ser.IsReading())
  1382.         {
  1383.                 m_behaviorSelectionTree.reset();
  1384.                 m_behaviorSelectionVariables.reset();
  1385.         }
  1386.  
  1387.         if (ser.IsReading())
  1388.         {
  1389.                 ResetBehaviorSelectionTree(AIOBJRESET_INIT);
  1390.         }
  1391.  
  1392.         if (ser.IsReading())
  1393.         {
  1394.                 ResetModularBehaviorTree(AIOBJRESET_INIT);
  1395.         }
  1396.  
  1397.         bool observer = m_observer;
  1398.         ser.Value("m_observer", observer);
  1399.  
  1400.         if (ser.IsReading())
  1401.         {
  1402.                 SetObserver(observer);
  1403.  
  1404.                 // only alive puppets or leaders should be added to groups
  1405.                 bool addToGroup = GetProxy() != NULL ? !GetProxy()->IsDead() : CastToCLeader() != NULL;
  1406.                 if (addToGroup)
  1407.                         GetAISystem()->AddToGroup(this);
  1408.  
  1409.                 ReactionChanged(0, IFactionMap::Hostile);
  1410.  
  1411.                 m_probableTargets.clear();
  1412.                 m_usingCombatLight = false;
  1413.                 m_lightLevel = AILL_LIGHT;
  1414.         }
  1415.  
  1416.         ser.Value("m_cachedWaterOcclusionValue", m_cachedWaterOcclusionValue);
  1417.  
  1418.         ser.Value("m_vLastFullUpdatePos", m_vLastFullUpdatePos);
  1419.         uint32 lastFullUpdateStance = m_lastFullUpdateStance;
  1420.         ser.Value("m_lastFullUpdateStance", lastFullUpdateStance);
  1421.         if (ser.IsReading())
  1422.         {
  1423.                 m_lastFullUpdateStance = static_cast<EStance>(lastFullUpdateStance);
  1424.         }
  1425.  
  1426.         if (ser.IsReading())
  1427.         {
  1428.                 SetAttentionTarget(NILREF);
  1429.         }
  1430.  
  1431.         ser.Value("m_bCloseContact", m_bCloseContact);
  1432.  
  1433.         // Territory
  1434.         ser.Value("m_territoryShapeName", m_territoryShapeName);
  1435.         if (ser.IsReading())
  1436.                 m_territoryShape = GetAISystem()->GetGenericShapeOfName(m_territoryShapeName.c_str());
  1437.  
  1438.         ser.Value("m_forcefullyHostiles", m_forcefullyHostiles);
  1439.  
  1440.         ser.Value("m_activeCoordinationCount", m_activeCoordinationCount);
  1441.  
  1442.         uint32 navigationTypeId = m_navigationTypeID;
  1443.         ser.Value("m_navigationTypeID", navigationTypeId);
  1444.         if (ser.IsReading())
  1445.         {
  1446.                 m_navigationTypeID = NavigationAgentTypeID(navigationTypeId);
  1447.         }
  1448.  
  1449.         ser.Value("m_currentCollisionAvoidanceRadiusIncrement", m_currentCollisionAvoidanceRadiusIncrement);
  1450.  
  1451.         ser.Value("m_initialPosition.isValid", m_initialPosition.isValid);
  1452.         ser.Value("m_initialPosition.pos", m_initialPosition.pos);
  1453. }
  1454.  
  1455. void CAIActor::SetAttentionTarget(CWeakRef<CAIObject> refTarget)
  1456. {
  1457.         CCCPOINT(CAIActor_SetAttentionTarget);
  1458.         CAIObject* pAttTarget = refTarget.GetAIObject();
  1459.  
  1460.         m_refAttentionTarget = refTarget;
  1461.  
  1462. #ifdef CRYAISYSTEM_DEBUG
  1463.         RecorderEventData recorderEventData(pAttTarget ? pAttTarget->GetName() : "<none>");
  1464.         RecordEvent(IAIRecordable::E_ATTENTIONTARGET, &recorderEventData);
  1465. #endif
  1466. }
  1467.  
  1468. Vec3 CAIActor::GetFloorPosition(const Vec3& pos)
  1469. {
  1470.         Vec3 floorPos = pos;
  1471.         return (GetFloorPos(floorPos, pos, WalkabilityFloorUpDist, WalkabilityFloorDownDist, WalkabilityDownRadius, AICE_STATIC))
  1472.                ? floorPos : pos;
  1473. }
  1474.  
  1475. void CAIActor::CheckCloseContact(IAIObject* pTarget, float distSq)
  1476. {
  1477.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  1478.         if (!m_bCloseContact && distSq < sqr(GetParameters().m_fMeleeRange))
  1479.         {
  1480.                 SetSignal(1, "OnCloseContact", pTarget->GetEntity(), 0, gAIEnv.SignalCRCs.m_nOnCloseContact);
  1481.                 SetCloseContact(true);
  1482.         }
  1483. }
  1484.  
  1485. void CAIActor::SetCloseContact(bool bCloseContact)
  1486. {
  1487.         if (bCloseContact && !m_bCloseContact)
  1488.                 m_CloseContactTime = GetAISystem()->GetFrameStartTime();
  1489.         m_bCloseContact = bCloseContact;
  1490. }
  1491.  
  1492. IAIObject::EFieldOfViewResult CAIActor::IsObjectInFOV(CAIObject* pTarget, float fDistanceScale) const
  1493. {
  1494.         CCCPOINT(CAIActor_IsObjectInFOVCone);
  1495.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  1496.  
  1497.         const Vec3& vTargetPos = pTarget->GetPos();
  1498.         const float fSightRange = GetMaxTargetVisibleRange(pTarget) * fDistanceScale;
  1499.         return (fSightRange > 0.0f ? CheckPointInFOV(vTargetPos, fSightRange) : eFOV_Outside);
  1500. }
  1501.  
  1502. CWeakRef<CAIActor> CAIActor::GetLiveTarget(const CWeakRef<CAIObject>& refTarget)
  1503. {
  1504.         CCCPOINT(CPuppet_GetLiveTarget);
  1505.  
  1506.         CWeakRef<CAIActor> refResult;
  1507.         CAIObject* pTarget = refTarget.GetAIObject();
  1508.         if (pTarget)
  1509.         {
  1510.                 CAIActor* pAIActor = pTarget->CastToCAIActor();
  1511.                 if (pAIActor && pAIActor->IsActive() && pAIActor->IsAgent())
  1512.                 {
  1513.                         refResult = StaticCast<CAIActor>(refTarget);
  1514.                 }
  1515.                 else
  1516.                 {
  1517.                         CAIActor* pAssociatedAIActor = CastToCAIActorSafe(pTarget->GetAssociation().GetAIObject());
  1518.                         if (pAssociatedAIActor && pAssociatedAIActor->IsEnabled() && pAssociatedAIActor->IsAgent())
  1519.                         {
  1520.                                 refResult = GetWeakRef(pAssociatedAIActor);
  1521.                         }
  1522.                 }
  1523.         }
  1524.         return refResult;
  1525. }
  1526.  
  1527. const CAIObject* CAIActor::GetLiveTarget(const CAIObject* pTarget)
  1528. {
  1529.         if (!pTarget)
  1530.                 return 0;
  1531.         if (const CAIActor* pTargetAIActor = pTarget->CastToCAIActor())
  1532.                 if (!pTargetAIActor->IsActive())
  1533.                         return 0;
  1534.         if (pTarget->IsAgent())
  1535.                 return pTarget;
  1536.         const CAIObject* pAssociation = pTarget->GetAssociation().GetAIObject();
  1537.         return (pAssociation && pAssociation->IsEnabled() && pAssociation->IsAgent()) ? pAssociation : 0;
  1538. }
  1539.  
  1540. uint32 CAIActor::GetFactionVisionMask(uint8 factionID) const
  1541. {
  1542.         uint32 mask = 0;
  1543.         uint32 factionCount = gAIEnv.pFactionMap->GetFactionCount();
  1544.  
  1545.         for (uint32 i = 0; i < factionCount; ++i)
  1546.         {
  1547.                 if (i != factionID)
  1548.                 {
  1549.                         if (gAIEnv.pFactionMap->GetReaction(factionID, i) < IFactionMap::Neutral)
  1550.                                 mask |= 1 << i;
  1551.                 }
  1552.         }
  1553.  
  1554.         PersonallyHostiles::const_iterator it = m_forcefullyHostiles.begin();
  1555.         PersonallyHostiles::const_iterator end = m_forcefullyHostiles.end();
  1556.  
  1557.         for (; it != end; ++it)
  1558.         {
  1559.                 if (const CAIObject* aiObject = static_cast<const CAIObject*>(GetAISystem()->GetAIObjectManager()->GetAIObject(*it)))
  1560.                         if (aiObject->GetFactionID() != IFactionMap::InvalidFactionID)
  1561.                                 mask |= 1 << aiObject->GetFactionID();
  1562.         }
  1563.  
  1564.         return mask;
  1565. }
  1566.  
  1567. void CAIActor::SerializeMovementAbility(TSerialize ser)
  1568. {
  1569.         ser.BeginGroup("AgentMovementAbility");
  1570.         AgentMovementAbility& moveAbil = m_movementAbility;
  1571.  
  1572.         ser.Value("b3DMove", moveAbil.b3DMove);
  1573.         ser.Value("bUsePathfinder", moveAbil.bUsePathfinder);
  1574.         ser.Value("usePredictiveFollowing", moveAbil.usePredictiveFollowing);
  1575.         ser.Value("allowEntityClampingByAnimation", moveAbil.allowEntityClampingByAnimation);
  1576.         ser.Value("maxAccel", moveAbil.maxAccel);
  1577.         ser.Value("maxDecel", moveAbil.maxDecel);
  1578.         ser.Value("minTurnRadius", moveAbil.minTurnRadius);
  1579.         ser.Value("maxTurnRadius", moveAbil.maxTurnRadius);
  1580.         ser.Value("avoidanceRadius", moveAbil.avoidanceRadius);
  1581.         ser.Value("pathLookAhead", moveAbil.pathLookAhead);
  1582.         ser.Value("pathRadius", moveAbil.pathRadius);
  1583.         ser.Value("pathSpeedLookAheadPerSpeed", moveAbil.pathSpeedLookAheadPerSpeed);
  1584.         ser.Value("cornerSlowDown", moveAbil.cornerSlowDown);
  1585.         ser.Value("slopeSlowDown", moveAbil.slopeSlowDown);
  1586.         ser.Value("optimalFlightHeight", moveAbil.optimalFlightHeight);
  1587.         ser.Value("minFlightHeight", moveAbil.minFlightHeight);
  1588.         ser.Value("maxFlightHeight", moveAbil.maxFlightHeight);
  1589.         ser.Value("maneuverTrh", moveAbil.maneuverTrh);
  1590.         ser.Value("velDecay", moveAbil.velDecay);
  1591.         ser.Value("pathFindPrediction", moveAbil.pathFindPrediction);
  1592.         ser.Value("pathRegenIntervalDuringTrace", moveAbil.pathRegenIntervalDuringTrace);
  1593.         ser.Value("teleportEnabled", moveAbil.teleportEnabled);
  1594.         ser.Value("lightAffectsSpeed", moveAbil.lightAffectsSpeed);
  1595.         ser.Value("resolveStickingInTrace", moveAbil.resolveStickingInTrace);
  1596.         ser.Value("directionalScaleRefSpeedMin", moveAbil.directionalScaleRefSpeedMin);
  1597.         ser.Value("directionalScaleRefSpeedMax", moveAbil.directionalScaleRefSpeedMax);
  1598.         ser.Value("avoidanceAbilities", moveAbil.avoidanceAbilities);
  1599.         ser.Value("pushableObstacleWeakAvoidance", moveAbil.pushableObstacleWeakAvoidance);
  1600.         ser.Value("pushableObstacleAvoidanceRadius", moveAbil.pushableObstacleAvoidanceRadius);
  1601.         ser.Value("pushableObstacleMassMin", moveAbil.pushableObstacleMassMin);
  1602.         ser.Value("pushableObstacleMassMax", moveAbil.pushableObstacleMassMax);
  1603.  
  1604.         ser.BeginGroup("AgentMovementSpeeds");
  1605.  
  1606.         AgentMovementSpeeds& moveSpeeds = m_movementAbility.movementSpeeds;
  1607.         for (int i = 0; i < AgentMovementSpeeds::AMU_NUM_VALUES; i++)
  1608.                 for (int j = 0; j < AgentMovementSpeeds::AMS_NUM_VALUES; j++)
  1609.                 {
  1610.                         ser.BeginGroup("range");
  1611.                         AgentMovementSpeeds::SSpeedRange& range = moveSpeeds.GetRange(j, i);
  1612.                         ser.Value("def", range.def);
  1613.                         ser.Value("min", range.min);
  1614.                         ser.Value("max", range.max);
  1615.                         ser.EndGroup();
  1616.                 }
  1617.  
  1618.         ser.EndGroup();
  1619.  
  1620.         ser.BeginGroup("AgentPathfindingProperties");
  1621.         AgentPathfindingProperties& pfProp = m_movementAbility.pathfindingProperties;
  1622.  
  1623.         pfProp.navCapMask.Serialize(ser);
  1624.         ser.Value("triangularResistanceFactor", pfProp.triangularResistanceFactor);
  1625.         ser.Value("waypointResistanceFactor", pfProp.waypointResistanceFactor);
  1626.         ser.Value("flightResistanceFactor", pfProp.flightResistanceFactor);
  1627.         ser.Value("volumeResistanceFactor", pfProp.volumeResistanceFactor);
  1628.         ser.Value("roadResistanceFactor", pfProp.roadResistanceFactor);
  1629.  
  1630.         ser.Value("waterResistanceFactor", pfProp.waterResistanceFactor);
  1631.         ser.Value("maxWaterDepth", pfProp.maxWaterDepth);
  1632.         ser.Value("minWaterDepth", pfProp.minWaterDepth);
  1633.         ser.Value("exposureFactor", pfProp.exposureFactor);
  1634.         ser.Value("dangerCost", pfProp.dangerCost);
  1635.         ser.Value("zScale", pfProp.zScale);
  1636.  
  1637.         ser.EndGroup();
  1638.  
  1639.         ser.EndGroup();
  1640. }
  1641.  
  1642. //
  1643. //------------------------------------------------------------------------------------------------------------------------
  1644. float CAIActor::AdjustTargetVisibleRange(const CAIActor& observer, float fVisibleRange) const
  1645. {
  1646.         return fVisibleRange;
  1647. }
  1648.  
  1649. //
  1650. //------------------------------------------------------------------------------------------------------------------------
  1651. float CAIActor::GetMaxTargetVisibleRange(const IAIObject* pTarget, bool bCheckCloak) const
  1652. {
  1653.         float fRange = 0.0f;
  1654.  
  1655.         const AgentParameters& parameters = GetParameters();
  1656.         const AgentPerceptionParameters& perception = parameters.m_PerceptionParams;
  1657.  
  1658.         IAIActor::CloakObservability cloakObservability;
  1659.         cloakObservability.cloakMaxDistCrouchedAndMoving = perception.cloakMaxDistCrouchedAndMoving;
  1660.         cloakObservability.cloakMaxDistCrouchedAndStill = perception.cloakMaxDistCrouchedAndStill;
  1661.         cloakObservability.cloakMaxDistMoving = perception.cloakMaxDistMoving;
  1662.         cloakObservability.cloakMaxDistStill = perception.cloakMaxDistStill;
  1663.  
  1664.         // Check if I'm invisible from the observer's position
  1665.         const CAIActor* pTargetActor = CastToCAIActorSafe(pTarget);
  1666.         if (!pTargetActor || !pTargetActor->IsInvisibleFrom(GetPos(), bCheckCloak, true, cloakObservability))
  1667.         {
  1668.                 fRange = perception.sightRange;
  1669.  
  1670.                 if (pTarget)
  1671.                 {
  1672.                         // Use correct range for vehicles
  1673.                         if (pTarget->GetAIType() == AIOBJECT_VEHICLE && parameters.m_PerceptionParams.sightRangeVehicle > FLT_EPSILON)
  1674.                         {
  1675.                                 fRange = parameters.m_PerceptionParams.sightRangeVehicle;
  1676.                         }
  1677.  
  1678.                         // Allow target to adjust the visible range as needed. This allows effects like
  1679.                         //      underwater occlusion or light levels to take effect.
  1680.                         if (pTargetActor && fRange > FLT_EPSILON)
  1681.                         {
  1682.                                 fRange = pTargetActor->AdjustTargetVisibleRange(*this, fRange);
  1683.                         }
  1684.                 }
  1685.         }
  1686.  
  1687.         return fRange;
  1688. }
  1689.  
  1690. //
  1691. //------------------------------------------------------------------------------------------------------------------------
  1692. bool CAIActor::IsCloakEffective(const Vec3& pos) const
  1693. {
  1694.         return (m_Parameters.m_fCloakScaleTarget > 0.f &&
  1695.                 !IsUsingCombatLight() &&
  1696.                 (!GetGrabbedEntity() || !IsGrabbedEntityInView(pos)));
  1697. }
  1698.  
  1699. //
  1700. //------------------------------------------------------------------------------------------------------------------------
  1701. bool CAIActor::IsInvisibleFrom(const Vec3& pos, bool bCheckCloak, bool bCheckCloakDistance, const IAIActor::CloakObservability& cloakObservability) const
  1702. {
  1703.         bool bInvisible = (m_Parameters.m_bInvisible);
  1704.  
  1705.         if (!bInvisible && bCheckCloak)
  1706.         {
  1707.                 bInvisible = (m_Parameters.m_bCloaked && IsCloakEffective(pos));
  1708.  
  1709.                 // Cloaked targets can still be seen if they are close enough to the point
  1710.                 if (bInvisible && bCheckCloakDistance)
  1711.                 {
  1712.                         float cloakMaxDist = 0.0f;
  1713.  
  1714.                         if (m_bodyInfo.stance == STANCE_CROUCH)
  1715.                         {
  1716.                                 cloakMaxDist = m_bodyInfo.isMoving ? cloakObservability.cloakMaxDistCrouchedAndMoving : cloakObservability.cloakMaxDistCrouchedAndStill;
  1717.                         }
  1718.                         else
  1719.                         {
  1720.                                 cloakMaxDist = m_bodyInfo.isMoving ? cloakObservability.cloakMaxDistMoving : cloakObservability.cloakMaxDistStill;
  1721.                         }
  1722.  
  1723.                         bInvisible = Distance::Point_PointSq(GetPos(), pos) > sqr(cloakMaxDist);
  1724.                 }
  1725.         }
  1726.  
  1727.         return bInvisible;
  1728. }
  1729.  
  1730. //
  1731. //------------------------------------------------------------------------------------------------------------------------
  1732. void CAIActor::NotifyDeath()
  1733. {
  1734. }
  1735.  
  1736. //
  1737. //------------------------------------------------------------------------------------------------------------------------
  1738. static void CheckAndAddPhysEntity(PhysSkipList& skipList, IPhysicalEntity* physics)
  1739. {
  1740.         if (physics)
  1741.         {
  1742.                 pe_status_pos stat;
  1743.  
  1744.                 if ((physics->GetStatus(&stat) != 0) && (((1 << stat.iSimClass) & COVER_OBJECT_TYPES) != 0))
  1745.                 {
  1746.                         stl::push_back_unique(skipList, physics);
  1747.                 }
  1748.         }
  1749. }
  1750.  
  1751. //
  1752. //------------------------------------------------------------------------------------------------------------------------
  1753. void CAIActor::GetPhysicalSkipEntities(PhysSkipList& skipList) const
  1754. {
  1755.         CAIObject::GetPhysicalSkipEntities(skipList);
  1756.  
  1757.         const SAIBodyInfo& bi = GetBodyInfo();
  1758.         if (IEntity* pLinkedVehicleEntity = bi.GetLinkedVehicleEntity())
  1759.         {
  1760.                 CheckAndAddPhysEntity(skipList, pLinkedVehicleEntity->GetPhysics());
  1761.         }
  1762.  
  1763.         // if holding something in hands - skip it for the vis check
  1764.         IEntity* pGrabbedEntity(GetGrabbedEntity());
  1765.         if (pGrabbedEntity)
  1766.                 CheckAndAddPhysEntity(skipList, pGrabbedEntity->GetPhysics());
  1767.  
  1768.         // (Kevin) Adding children in most cases causes us to add too many entities to the skip list (i.e., vehicles)
  1769.         // If this is needed, investigate how we can keep this under 5 skippable entities.
  1770.         /*if (IEntity* entity = GetEntity())
  1771.            {
  1772.            for (int i = 0, ni = entity->GetChildCount(); i < ni; ++i)
  1773.            {
  1774.             if (IEntity* child = entity->GetChild(i))
  1775.               CheckAndAddPhysEntity(skipList, child->GetPhysics());
  1776.            }
  1777.            }*/
  1778.  
  1779.         CRY_ASSERT_MESSAGE(skipList.size() <= 5, "Too many physical skipped entities determined. See SRwiRequest definition.");
  1780. }
  1781.  
  1782. void CAIActor::UpdateObserverSkipList()
  1783. {
  1784.         if (m_observer)
  1785.         {
  1786.                 PhysSkipList skipList;
  1787.                 GetPhysicalSkipEntities(skipList);
  1788.  
  1789.                 assert(skipList.size() <= ObserverParams::MaxSkipListSize);
  1790.  
  1791.                 ObserverParams observerParams;
  1792.                 observerParams.skipListSize = std::min<size_t>(skipList.size(), ObserverParams::MaxSkipListSize);
  1793.                 for (size_t i = 0; i < static_cast<size_t>(observerParams.skipListSize); ++i)
  1794.                         observerParams.skipList[i] = skipList[i];
  1795.  
  1796.                 gAIEnv.pVisionMap->ObserverChanged(GetVisionID(), observerParams, eChangedSkipList);
  1797.         }
  1798. }
  1799.  
  1800. void CAIActor::GetLocalBounds(AABB& bbox) const
  1801. {
  1802.         bbox.min.zero();
  1803.         bbox.max.zero();
  1804.  
  1805.         IEntity* pEntity = GetEntity();
  1806.         IPhysicalEntity* pPhysicalEntity = pEntity->GetPhysics();
  1807.         if (pPhysicalEntity)
  1808.         {
  1809.                 pe_status_pos pstate;
  1810.                 if (pPhysicalEntity && pPhysicalEntity->GetStatus(&pstate))
  1811.                 {
  1812.                         bbox.min = pstate.BBox[0] / pstate.scale;
  1813.                         bbox.max = pstate.BBox[1] / pstate.scale;
  1814.                 }
  1815.         }
  1816.         else
  1817.         {
  1818.                 return pEntity->GetLocalBounds(bbox);
  1819.         }
  1820. }
  1821.  
  1822. IEntity* CAIActor::GetPathAgentEntity() const
  1823. {
  1824.         return GetEntity();
  1825. }
  1826.  
  1827. const char* CAIActor::GetPathAgentName() const
  1828. {
  1829.         return GetName();
  1830. }
  1831.  
  1832. unsigned short CAIActor::GetPathAgentType() const
  1833. {
  1834.         return GetType();
  1835. }
  1836.  
  1837. float CAIActor::GetPathAgentPassRadius() const
  1838. {
  1839.         return GetParameters().m_fPassRadius;
  1840. }
  1841.  
  1842. Vec3 CAIActor::GetPathAgentPos() const
  1843. {
  1844.         return GetPhysicsPos();
  1845. }
  1846.  
  1847. Vec3 CAIActor::GetPathAgentVelocity() const
  1848. {
  1849.         return GetVelocity();
  1850. }
  1851.  
  1852. void CAIActor::GetPathAgentNavigationBlockers(NavigationBlockers& navigationBlockers, const struct PathfindRequest* pRequest)
  1853. {
  1854.  
  1855. }
  1856.  
  1857. size_t CAIActor::GetNavNodeIndex() const
  1858. {
  1859.         if (m_lastNavNodeIndex)
  1860.                 return (m_lastNavNodeIndex < ~0ul) ? m_lastNavNodeIndex : 0;
  1861.  
  1862.         m_lastNavNodeIndex = ~0ul;
  1863.  
  1864.         return 0;
  1865. }
  1866.  
  1867. const AgentMovementAbility& CAIActor::GetPathAgentMovementAbility() const
  1868. {
  1869.         return m_movementAbility;
  1870. }
  1871.  
  1872. unsigned int CAIActor::GetPathAgentLastNavNode() const
  1873. {
  1874.         return GetNavNodeIndex();
  1875. }
  1876.  
  1877. void CAIActor::SetPathAgentLastNavNode(unsigned int lastNavNode)
  1878. {
  1879.         m_lastNavNodeIndex = lastNavNode;
  1880. }
  1881.  
  1882. void CAIActor::SetPathToFollow(const char* pathName)
  1883. {
  1884.  
  1885. }
  1886.  
  1887. void CAIActor::SetPathAttributeToFollow(bool bSpline)
  1888. {
  1889.  
  1890. }
  1891.  
  1892. void CAIActor::SetPFBlockerRadius(int blockerType, float radius)
  1893. {
  1894.  
  1895. }
  1896.  
  1897. ETriState CAIActor::CanTargetPointBeReached(CTargetPointRequest& request)
  1898. {
  1899.         request.SetResult(eTS_false);
  1900.         return eTS_false;
  1901. }
  1902.  
  1903. bool CAIActor::UseTargetPointRequest(const CTargetPointRequest& request)
  1904. {
  1905.         return false;
  1906. }
  1907.  
  1908. IPathFollower* CAIActor::GetPathFollower() const
  1909. {
  1910.         return NULL;
  1911. }
  1912.  
  1913. bool CAIActor::GetValidPositionNearby(const Vec3& proposedPosition, Vec3& adjustedPosition) const
  1914. {
  1915.         return false;
  1916. }
  1917.  
  1918. bool CAIActor::GetTeleportPosition(Vec3& teleportPos) const
  1919. {
  1920.         return false;
  1921. }
  1922.  
  1923. //===================================================================
  1924. // GetSightFOVCos
  1925. //===================================================================
  1926. void CAIActor::GetSightFOVCos(float& fPrimaryFOVCos, float& fSecondaryFOVCos) const
  1927. {
  1928.         fPrimaryFOVCos = m_FOVPrimaryCos;
  1929.         fSecondaryFOVCos = m_FOVSecondaryCos;
  1930. }
  1931.  
  1932. //===================================================================
  1933. // TransformFOV
  1934. //===================================================================
  1935. void CAIActor::CacheFOVCos(float FOVPrimary, float FOVSecondary)
  1936. {
  1937.         if (FOVPrimary < 0.0f || FOVPrimary > 360.0f)   // see all around
  1938.         {
  1939.                 m_FOVPrimaryCos = -1.0f;
  1940.                 m_FOVSecondaryCos = -1.0f;
  1941.         }
  1942.         else
  1943.         {
  1944.                 if (FOVSecondary >= 0.0f && FOVPrimary > FOVSecondary)
  1945.                         FOVSecondary = FOVPrimary;
  1946.  
  1947.                 m_FOVPrimaryCos = cosf(DEG2RAD(FOVPrimary * 0.5f));
  1948.  
  1949.                 if (FOVSecondary < 0.0f || FOVSecondary > 360.0f)   // see all around
  1950.                         m_FOVSecondaryCos = -1.0f;
  1951.                 else
  1952.                         m_FOVSecondaryCos = cosf(DEG2RAD(FOVSecondary * 0.5f));
  1953.         }
  1954. }
  1955.  
  1956. void CAIActor::ReactionChanged(uint8 factionID, IFactionMap::ReactionType reaction)
  1957. {
  1958.         if (m_observer)
  1959.         {
  1960.                 ObserverParams params;
  1961.                 uint8 faction = GetFactionID();
  1962.                 params.factionsToObserveMask = GetFactionVisionMask(faction);
  1963.                 params.faction = faction;
  1964.  
  1965.                 gAIEnv.pVisionMap->ObserverChanged(GetVisionID(), params, eChangedFaction | eChangedFactionsToObserveMask);
  1966.         }
  1967. }
  1968.  
  1969. void CAIActor::VisionChanged(float sightRange, float primaryFOVCos, float secondaryFOVCos)
  1970. {
  1971.         if (m_observer)
  1972.         {
  1973.                 ObserverParams observerParams;
  1974.                 observerParams.sightRange = sightRange;
  1975.                 observerParams.fovCos = primaryFOVCos;
  1976.  
  1977.                 gAIEnv.pVisionMap->ObserverChanged(GetVisionID(), observerParams, eChangedSightRange | eChangedFOV);
  1978.         }
  1979. }
  1980.  
  1981. void CAIActor::SetObserver(bool observer)
  1982. {
  1983.         if (m_observer != observer)
  1984.         {
  1985.                 if (observer)
  1986.                 {
  1987.                         uint8 faction = GetFactionID();
  1988.                         ObserverParams observerParams;
  1989.                         observerParams.entityId = GetEntityID();
  1990.                         observerParams.factionsToObserveMask = GetFactionVisionMask(faction);
  1991.                         observerParams.faction = faction;
  1992.                         observerParams.typesToObserveMask = GetObserverTypeMask();
  1993.                         observerParams.typeMask = GetObservableTypeMask();
  1994.                         observerParams.eyePosition = GetPos();
  1995.                         observerParams.eyeDirection = GetViewDir();
  1996.                         observerParams.fovCos = m_FOVPrimaryCos;
  1997.                         observerParams.sightRange = m_Parameters.m_PerceptionParams.sightRange;
  1998.  
  1999.                         PhysSkipList skipList;
  2000.                         GetPhysicalSkipEntities(skipList);
  2001.  
  2002.                         observerParams.skipListSize = std::min<size_t>(skipList.size(), ObserverParams::MaxSkipListSize);
  2003.                         for (size_t i = 0; i < static_cast<size_t>(observerParams.skipListSize); ++i)
  2004.                                 observerParams.skipList[i] = skipList[i];
  2005.  
  2006.                         VisionID visionID = GetVisionID();
  2007.                         if (!visionID)
  2008.                         {
  2009.                                 visionID = gAIEnv.pVisionMap->CreateVisionID(GetName());
  2010.  
  2011.                                 SetVisionID(visionID);
  2012.                         }
  2013.  
  2014.                         gAIEnv.pVisionMap->RegisterObserver(visionID, observerParams);
  2015.                 }
  2016.                 else
  2017.                 {
  2018.                         if (VisionID visionID = GetVisionID())
  2019.                                 gAIEnv.pVisionMap->UnregisterObserver(visionID);
  2020.                 }
  2021.  
  2022.                 m_observer = observer;
  2023.         }
  2024. }
  2025.  
  2026. uint32 CAIActor::GetObserverTypeMask() const
  2027. {
  2028.         return General | AliveAgent | DeadAgent | Player;
  2029. }
  2030.  
  2031. uint32 CAIActor::GetObservableTypeMask() const
  2032. {
  2033.         return General | AliveAgent;
  2034. }
  2035.  
  2036. bool CAIActor::IsObserver() const
  2037. {
  2038.         return m_observer;
  2039. }
  2040.  
  2041. bool CAIActor::CanSee(const VisionID& otherID) const
  2042. {
  2043.         return gEnv->pAISystem->GetVisionMap()->IsVisible(GetVisionID(), otherID);
  2044. }
  2045.  
  2046. void CAIActor::AddPersonallyHostile(tAIObjectID hostileID)
  2047. {
  2048.         m_forcefullyHostiles.insert(hostileID);
  2049.  
  2050.         ReactionChanged(0, IFactionMap::Hostile);
  2051. }
  2052.  
  2053. void CAIActor::RemovePersonallyHostile(tAIObjectID hostileID)
  2054. {
  2055.         m_forcefullyHostiles.erase(hostileID);
  2056.  
  2057.         ReactionChanged(0, IFactionMap::Hostile);
  2058. }
  2059.  
  2060. void CAIActor::ResetPersonallyHostiles()
  2061. {
  2062.         m_forcefullyHostiles.clear();
  2063.  
  2064.         ReactionChanged(0, IFactionMap::Hostile);
  2065. }
  2066.  
  2067. bool CAIActor::IsPersonallyHostile(tAIObjectID hostileID) const
  2068. {
  2069.         return m_forcefullyHostiles.find(hostileID) != m_forcefullyHostiles.end();
  2070. }
  2071.  
  2072. void CAIActor::SetProxy(IAIActorProxy* proxy)
  2073. {
  2074.         m_proxy.reset(proxy);
  2075. }
  2076.  
  2077. IAIActorProxy* CAIActor::GetProxy() const
  2078. {
  2079.         return m_proxy;
  2080. }
  2081.  
  2082. void CAIActor::ClearProbableTargets()
  2083. {
  2084.         m_probableTargets.clear();
  2085. }
  2086.  
  2087. void CAIActor::AddProbableTarget(CAIObject* pTarget)
  2088. {
  2089.         m_probableTargets.push_back(pTarget);
  2090. }
  2091.  
  2092. IAIObject::EFieldOfViewResult CAIActor::CheckPointInFOV(const Vec3& point, float sightRange) const
  2093. {
  2094.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  2095.  
  2096.         const Vec3& eyePosition = GetPos();
  2097.         const Vec3 eyeToPointDisplacement = point - eyePosition;
  2098.         const float squaredEyeToPointDistance = eyeToPointDisplacement.GetLengthSquared();
  2099.  
  2100.         const bool pointIsAtEyePosition = (squaredEyeToPointDistance <= std::numeric_limits<float>::epsilon());
  2101.         IF_UNLIKELY (pointIsAtEyePosition)
  2102.                 return eFOV_Outside;
  2103.  
  2104.         if (squaredEyeToPointDistance <= sqr(sightRange))
  2105.         {
  2106.                 float primaryFovCos = 1.0f;
  2107.                 float secondaryFovCos = 1.0f;
  2108.                 GetSightFOVCos(primaryFovCos, secondaryFovCos);
  2109.                 assert(primaryFovCos >= secondaryFovCos);
  2110.  
  2111.                 const Vec3 eyeToPointDirection = eyeToPointDisplacement.GetNormalized();
  2112.                 const Vec3& eyeDirection = GetViewDir();
  2113.  
  2114.                 const float dotProduct = eyeDirection.Dot(eyeToPointDirection);
  2115.                 if (dotProduct >= secondaryFovCos)
  2116.                 {
  2117.                         if (dotProduct >= primaryFovCos)
  2118.                                 return eFOV_Primary;
  2119.                         else
  2120.                                 return eFOV_Secondary;
  2121.                 }
  2122.         }
  2123.  
  2124.         return eFOV_Outside;
  2125. }
  2126.  
  2127. void CAIActor::HandlePathDecision(MNMPathRequestResult& result)
  2128. {
  2129. }
  2130.  
  2131. void CAIActor::HandleVisualStimulus(SAIEVENT* pAIEvent)
  2132. {
  2133.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  2134.  
  2135.         const float fGlobalVisualPerceptionScale = gEnv->pAISystem->GetGlobalVisualScale(this);
  2136.         const float fVisualPerceptionScale = m_Parameters.m_PerceptionParams.perceptionScale.visual * fGlobalVisualPerceptionScale;
  2137.         if (gAIEnv.CVars.IgnoreVisualStimulus != 0 || m_Parameters.m_bAiIgnoreFgNode || fVisualPerceptionScale <= 0.0f)
  2138.                 return;
  2139.  
  2140.         if (gAIEnv.pTargetTrackManager->IsEnabled())
  2141.         {
  2142.                 // Check if in range (using perception scale)
  2143.                 if (eFOV_Outside != IsPointInFOV(pAIEvent->vPosition, fVisualPerceptionScale))
  2144.                 {
  2145.                         gAIEnv.pTargetTrackManager->HandleStimulusFromAIEvent(GetAIObjectID(), pAIEvent, TargetTrackHelpers::eEST_Visual);
  2146.  
  2147.                         IEntity* pEventOwnerEntity = gEnv->pEntitySystem->GetEntity(pAIEvent->sourceId);
  2148.                         if (!pEventOwnerEntity)
  2149.                                 return;
  2150.  
  2151.                         IAIObject* pEventOwnerAI = pEventOwnerEntity->GetAI();
  2152.                         if (!pEventOwnerAI)
  2153.                                 return;
  2154.  
  2155.                         if (IsHostile(pEventOwnerAI))
  2156.                         {
  2157.                                 m_State.nTargetType = static_cast<CAIObject*>(pEventOwnerAI)->GetType();
  2158.                                 m_stimulusStartTime = GetAISystem()->GetFrameStartTimeSeconds();
  2159.  
  2160.                                 m_State.eTargetThreat = AITHREAT_AGGRESSIVE;
  2161.                                 m_State.eTargetType = AITARGET_VISUAL;
  2162.  
  2163.                                 CWeakRef<CAIObject> refAttentionTarget = GetWeakRef(static_cast<CAIObject*>(pEventOwnerAI));
  2164.                                 if (refAttentionTarget != m_refAttentionTarget)
  2165.                                 {
  2166.                                         SetAttentionTarget(refAttentionTarget);
  2167.                                 }
  2168.                         }
  2169.                 }
  2170.         }
  2171. }
  2172.  
  2173. void CAIActor::HandleSoundEvent(SAIEVENT* pAIEvent)
  2174. {
  2175.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  2176.  
  2177.         const float fGlobalAudioPerceptionScale = gEnv->pAISystem->GetGlobalAudioScale(this);
  2178.         const float fAudioPerceptionScale = m_Parameters.m_PerceptionParams.perceptionScale.audio * fGlobalAudioPerceptionScale;
  2179.         if (gAIEnv.CVars.IgnoreSoundStimulus != 0 || m_Parameters.m_bAiIgnoreFgNode || fAudioPerceptionScale <= 0.0f)
  2180.                 return;
  2181.  
  2182.         if (gAIEnv.pTargetTrackManager->IsEnabled())
  2183.         {
  2184.                 // Check if in range (using perception scale)
  2185.                 const Vec3& vMyPos = GetPos();
  2186.                 const float fSoundDistance = vMyPos.GetDistance(pAIEvent->vPosition) * (1.0f / fAudioPerceptionScale);
  2187.                 if (fSoundDistance <= pAIEvent->fThreat)
  2188.                 {
  2189.                         gAIEnv.pTargetTrackManager->HandleStimulusFromAIEvent(GetAIObjectID(), pAIEvent, TargetTrackHelpers::eEST_Sound);
  2190.  
  2191.                         IEntity* pEventOwnerEntity = gEnv->pEntitySystem->GetEntity(pAIEvent->sourceId);
  2192.                         if (!pEventOwnerEntity)
  2193.                                 return;
  2194.  
  2195.                         IAIObject* pEventOwnerAI = pEventOwnerEntity->GetAI();
  2196.                         if (!pEventOwnerAI)
  2197.                                 return;
  2198.  
  2199.                         if (IsHostile(pEventOwnerAI))
  2200.                         {
  2201.                                 if ((m_State.eTargetType != AITARGET_MEMORY) && (m_State.eTargetType != AITARGET_VISUAL))
  2202.                                 {
  2203.                                         m_State.nTargetType = static_cast<CAIObject*>(pEventOwnerAI)->GetType();
  2204.                                         m_stimulusStartTime = GetAISystem()->GetFrameStartTimeSeconds();
  2205.  
  2206.                                         m_State.nTargetType = static_cast<CAIObject*>(pEventOwnerAI)->GetType();
  2207.                                         m_State.eTargetThreat = AITHREAT_AGGRESSIVE;
  2208.                                         m_State.eTargetType = AITARGET_SOUND;
  2209.  
  2210.                                         SetAttentionTarget(GetWeakRef(static_cast<CAIObject*>(pEventOwnerAI)));
  2211.                                 }
  2212.                         }
  2213.                 }
  2214.         }
  2215. }
  2216.  
  2217. void CAIActor::HandleBulletRain(SAIEVENT* pAIEvent)
  2218. {
  2219.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  2220.  
  2221.         if (gAIEnv.CVars.IgnoreBulletRainStimulus || m_Parameters.m_bAiIgnoreFgNode)
  2222.                 return;
  2223.  
  2224.         IAISignalExtraData* pData = GetAISystem()->CreateSignalExtraData();
  2225.         pData->point = pAIEvent->vPosition;
  2226.         pData->point2 = pAIEvent->vStimPos;
  2227.         pData->nID = pAIEvent->sourceId;
  2228.         pData->fValue = pAIEvent->fThreat; // pressureMultiplier
  2229.  
  2230.         SetSignal(0, "OnBulletRain", GetEntity(), pData, gAIEnv.SignalCRCs.m_nOnBulletRain);
  2231.  
  2232.         if (gAIEnv.pTargetTrackManager->IsEnabled())
  2233.                 gAIEnv.pTargetTrackManager->HandleStimulusFromAIEvent(GetAIObjectID(), pAIEvent, TargetTrackHelpers::eEST_BulletRain);
  2234. }
  2235.  
  2236. void CAIActor::CancelRequestedPath(bool actorRemoved)
  2237. {
  2238.  
  2239. }
  2240.  
  2241. IAIObject::EFieldOfViewResult CAIActor::IsPointInFOV(const Vec3& vPos, float fDistanceScale) const
  2242. {
  2243.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  2244.  
  2245.         const float fSightRange = m_Parameters.m_PerceptionParams.sightRange * fDistanceScale;
  2246.         return CheckPointInFOV(vPos, fSightRange);
  2247. }
  2248.  
  2249. void CAIActor::GetMovementSpeedRange(float fUrgency, bool bSlowForStrafe, float& normalSpeed, float& minSpeed, float& maxSpeed) const
  2250. {
  2251.         AgentMovementSpeeds::EAgentMovementUrgency urgency;
  2252.         AgentMovementSpeeds::EAgentMovementStance stance;
  2253.  
  2254.         bool vehicle = GetType() == AIOBJECT_VEHICLE;
  2255.  
  2256.         if (fUrgency < 0.5f * (AISPEED_SLOW + AISPEED_WALK))
  2257.                 urgency = AgentMovementSpeeds::AMU_SLOW;
  2258.         else if (fUrgency < 0.5f * (AISPEED_WALK + AISPEED_RUN))
  2259.                 urgency = AgentMovementSpeeds::AMU_WALK;
  2260.         else if (fUrgency < 0.5f * (AISPEED_RUN + AISPEED_SPRINT))
  2261.                 urgency = AgentMovementSpeeds::AMU_RUN;
  2262.         else
  2263.                 urgency = AgentMovementSpeeds::AMU_SPRINT;
  2264.  
  2265.         if (IsAffectedByLight() && m_movementAbility.lightAffectsSpeed)
  2266.         {
  2267.                 // Disable sprinting in dark light conditions.
  2268.                 if (urgency == AgentMovementSpeeds::AMU_SPRINT)
  2269.                 {
  2270.                         EAILightLevel eAILightLevel = GetLightLevel();
  2271.                         if ((eAILightLevel == AILL_DARK) || (eAILightLevel == AILL_SUPERDARK))
  2272.                                 urgency = AgentMovementSpeeds::AMU_RUN;
  2273.                 }
  2274.         }
  2275.  
  2276.         const SAIBodyInfo& bodyInfo = GetBodyInfo();
  2277.  
  2278.         switch (bodyInfo.stance)
  2279.         {
  2280.         case STANCE_STEALTH:
  2281.                 stance = AgentMovementSpeeds::AMS_STEALTH;
  2282.                 break;
  2283.         case STANCE_CROUCH:
  2284.                 stance = AgentMovementSpeeds::AMS_CROUCH;
  2285.                 break;
  2286.         case STANCE_PRONE:
  2287.                 stance = AgentMovementSpeeds::AMS_PRONE;
  2288.                 break;
  2289.         case STANCE_SWIM:
  2290.                 stance = AgentMovementSpeeds::AMS_SWIM;
  2291.                 break;
  2292.         case STANCE_RELAXED:
  2293.                 stance = AgentMovementSpeeds::AMS_RELAXED;
  2294.                 break;
  2295.         case STANCE_ALERTED:
  2296.                 stance = AgentMovementSpeeds::AMS_ALERTED;
  2297.                 break;
  2298.         case STANCE_LOW_COVER:
  2299.                 stance = AgentMovementSpeeds::AMS_LOW_COVER;
  2300.                 break;
  2301.         case STANCE_HIGH_COVER:
  2302.                 stance = AgentMovementSpeeds::AMS_HIGH_COVER;
  2303.                 break;
  2304.         default:
  2305.                 stance = AgentMovementSpeeds::AMS_COMBAT;
  2306.                 break;
  2307.         }
  2308.  
  2309.         const float artificialMinSpeedMult = 1.0f;
  2310.  
  2311.         AgentMovementSpeeds::SSpeedRange fwdRange = m_movementAbility.movementSpeeds.GetRange(stance, urgency);
  2312.         fwdRange.min *= artificialMinSpeedMult;
  2313.         normalSpeed = fwdRange.def;
  2314.         minSpeed = fwdRange.min;
  2315.         maxSpeed = fwdRange.max;
  2316.  
  2317.         if (m_movementAbility.directionalScaleRefSpeedMin > 0.0f)
  2318.         {
  2319.                 float desiredSpeed = normalSpeed;
  2320.                 float desiredTurnSpeed = m_bodyTurningSpeed;
  2321.                 float travelAngle = Ang3::CreateRadZ(GetEntityDir(), GetMoveDir()); //m_State.vMoveDir);
  2322.  
  2323.                 const float refSpeedMin = m_movementAbility.directionalScaleRefSpeedMin;
  2324.                 const float refSpeedMax = m_movementAbility.directionalScaleRefSpeedMax;
  2325.  
  2326.                 // When a locomotion is slow (0.5-2.0f), then we can do this motion in all direction more or less at the same speed
  2327.                 float t = sqr(clamp_tpl((desiredSpeed - refSpeedMin) / (refSpeedMax - refSpeedMin), 0.0f, 1.0f));
  2328.                 float scaleLimit = clamp_tpl(0.8f * (1 - t) + 0.1f * t, 0.3f, 1.0f); //never scale more then 0.4 down
  2329.  
  2330.                 float turnSlowDownFactor = (gAIEnv.configuration.eCompatibilityMode == ECCM_CRYSIS2) ? 0.2f : 0.4f;
  2331.                 //adjust desired speed for turns
  2332.                 float speedScale = 1.0f - fabsf(desiredTurnSpeed * turnSlowDownFactor) / gf_PI;
  2333.                 speedScale = clamp_tpl(speedScale, scaleLimit, 1.0f);
  2334.  
  2335.                 //adjust desired speed when strafing and running backward
  2336.                 float strafeSlowDown = (gf_PI - fabsf(travelAngle * 0.60f)) / gf_PI;
  2337.                 strafeSlowDown = clamp_tpl(strafeSlowDown, scaleLimit, 1.0f);
  2338.  
  2339.                 //adjust desired speed when running uphill & downhill
  2340.                 float slopeSlowDown = (gf_PI - fabsf(DEG2RAD(bodyInfo.slopeAngle) / 12.0f)) / gf_PI;
  2341.                 slopeSlowDown = clamp_tpl(slopeSlowDown, scaleLimit, 1.0f);
  2342.  
  2343.                 float scale = min(speedScale, min(strafeSlowDown, slopeSlowDown));
  2344.  
  2345.                 normalSpeed *= scale;
  2346.                 Limit(normalSpeed, minSpeed, maxSpeed);
  2347.         }
  2348. }
  2349.  
  2350. void CAIActor::ResetLookAt()
  2351. {
  2352.         m_State.vLookTargetPos.zero();
  2353. }
  2354.  
  2355. bool CAIActor::SetLookAtPointPos(const Vec3& vPoint, bool bPriority)
  2356. {
  2357.         m_State.vLookTargetPos = vPoint;
  2358.  
  2359.         // Inspired by CPipeUser::SetLookAtPointPos [5/3/2010 evgeny]
  2360.         Vec3 vDesired = vPoint - GetPos();
  2361.         if (!m_movementAbility.b3DMove)
  2362.         {
  2363.                 vDesired.z = 0;
  2364.         }
  2365.         vDesired.NormalizeSafe();
  2366.  
  2367.         const SAIBodyInfo& bodyInfo = GetBodyInfo();
  2368.  
  2369.         Vec3 vCurrent = bodyInfo.vEyeDirAnim;
  2370.         if (!m_movementAbility.b3DMove)
  2371.         {
  2372.                 vCurrent.z = 0;
  2373.         }
  2374.         vCurrent.NormalizeSafe();
  2375.  
  2376.         // cos( 11.5deg ) ~ 0.98
  2377.         return 0.98f <= vCurrent.Dot(vDesired);
  2378. }
  2379.  
  2380. bool CAIActor::SetLookAtDir(const Vec3& vDir, bool bPriority)
  2381. {
  2382.         Vec3 vDirCopy = vDir;
  2383.         return vDirCopy.NormalizeSafe() ? SetLookAtPointPos(GetPos() + vDirCopy * 100.0f) : true;
  2384. }
  2385.  
  2386. void CAIActor::ResetBodyTargetDir()
  2387. {
  2388.         m_State.vBodyTargetDir.zero();
  2389. }
  2390.  
  2391. void CAIActor::SetBodyTargetDir(const Vec3& vDir)
  2392. {
  2393.         m_State.vBodyTargetDir = vDir;
  2394. }
  2395.  
  2396. void CAIActor::SetMoveTarget(const Vec3& vMoveTarget)
  2397. {
  2398.         m_State.vMoveTarget = vMoveTarget;
  2399. }
  2400.  
  2401. const Vec3& CAIActor::GetBodyTargetDir() const
  2402. {
  2403.         return m_State.vBodyTargetDir;
  2404. }
  2405.  
  2406. void CAIActor::GoTo(const Vec3& vTargetPos)
  2407. {
  2408.         m_State.vLookTargetPos = vTargetPos;
  2409.         m_State.vMoveTarget = vTargetPos;
  2410. }
  2411.  
  2412. void CAIActor::SetSpeed(float fSpeed)
  2413. {
  2414.         m_State.fMovementUrgency = fSpeed;
  2415. }
  2416.  
  2417. IPhysicalEntity* CAIActor::GetPhysics(bool bWantCharacterPhysics) const
  2418. {
  2419.         IAIActorProxy* pAIActorProxy = GetProxy();
  2420.         return pAIActorProxy ? pAIActorProxy->GetPhysics(bWantCharacterPhysics)
  2421.                : CAIObject::GetPhysics(bWantCharacterPhysics);
  2422. }
  2423.  
  2424. bool CAIActor::CanDamageTarget(IAIObject* target) const
  2425. {
  2426.         return true;
  2427. }
  2428.  
  2429. bool CAIActor::CanDamageTargetWithMelee() const
  2430. {
  2431.         return true;
  2432. }
  2433.  
  2434. void CAIActor::SetTerritoryShapeName(const char* szName)
  2435. {
  2436.         assert(szName);
  2437.  
  2438.         if (m_territoryShapeName.compare(szName))
  2439.         {
  2440.                 m_territoryShapeName = szName;
  2441.  
  2442.                 if (m_territoryShapeName.compare("<None>"))
  2443.                 {
  2444.                         m_territoryShape = GetAISystem()->GetGenericShapeOfName(szName);  // i.e. m_territoryShapeName
  2445.  
  2446.                         if (m_territoryShape)
  2447.                         {
  2448.                                 // Territory shapes should be really simple
  2449.                                 size_t size = m_territoryShape->shape.size();
  2450.                                 if (size > 8)
  2451.                                 {
  2452.                                         AIWarning("Territory shape %s for %s has %" PRISIZE_T " points.  Territories should not have more than 8 points",
  2453.                                                   szName, GetName(), size);
  2454.                                 }
  2455.                         }
  2456.                         else
  2457.                         {
  2458.                                 m_territoryShapeName += " (not found)";
  2459.                         }
  2460.                 }
  2461.                 else
  2462.                 {
  2463.                         m_territoryShape = 0;
  2464.                 }
  2465.         }
  2466. }
  2467.  
  2468. const char* CAIActor::GetTerritoryShapeName() const
  2469. {
  2470.         return (gEnv->IsEditor() && !gEnv->IsEditing())
  2471.                ? m_Parameters.m_sTerritoryName.c_str()
  2472.                : m_territoryShapeName.c_str();
  2473. }
  2474.  
  2475. bool CAIActor::IsPointInsideTerritoryShape(const Vec3& vPos, bool bCheckHeight) const
  2476. {
  2477.         bool bResult = true;
  2478.  
  2479.         const SShape* pTerritory = GetTerritoryShape();
  2480.         if (pTerritory)
  2481.         {
  2482.                 bResult = pTerritory->IsPointInsideShape(vPos, bCheckHeight);
  2483.         }
  2484.  
  2485.         return bResult;
  2486. }
  2487.  
  2488. bool CAIActor::ConstrainInsideTerritoryShape(Vec3& vPos, bool bCheckHeight) const
  2489. {
  2490.         bool bResult = true;
  2491.  
  2492.         const SShape* pTerritory = GetTerritoryShape();
  2493.         if (pTerritory)
  2494.         {
  2495.                 bResult = pTerritory->ConstrainPointInsideShape(vPos, bCheckHeight);
  2496.         }
  2497.  
  2498.         return bResult;
  2499. }
  2500.  
  2501. //===================================================================
  2502. // GetObjectType
  2503. //===================================================================
  2504. CAIActor::EAIObjectType CAIActor::GetObjectType(const CAIObject* ai, unsigned short type)
  2505. {
  2506.         if (type == AIOBJECT_PLAYER)
  2507.                 return AIOT_PLAYER;
  2508.         else if (type == AIOBJECT_ACTOR)
  2509.                 return AIOT_AGENTSMALL;
  2510.         else if (type == AIOBJECT_VEHICLE)
  2511.         {
  2512.                 // differentiate between medium and big vehicles (e.g. tank can drive over jeep)
  2513.                 return AIOT_AGENTMED;
  2514.         }
  2515.         else
  2516.                 return AIOT_UNKNOWN;
  2517. }
  2518.  
  2519. //===================================================================
  2520. // GetNavInteraction
  2521. //===================================================================
  2522. CAIActor::ENavInteraction CAIActor::GetNavInteraction(const CAIObject* navigator, const CAIObject* obstacle)
  2523. {
  2524.         if (const CAIActor* actor = navigator->CastToCAIActor())
  2525.         {
  2526.                 const SAIBodyInfo& info = actor->GetBodyInfo();
  2527.  
  2528.                 if (info.GetLinkedVehicleEntity())
  2529.                         return NI_IGNORE;
  2530.         }
  2531.  
  2532.         unsigned short navigatorType = navigator->GetType();
  2533.         unsigned short obstacleType = obstacle->GetType();
  2534.  
  2535.         bool enemy = navigator->IsHostile(obstacle);
  2536.  
  2537.         EAIObjectType navigatorOT = GetObjectType(navigator, navigatorType);
  2538.         EAIObjectType obstacleOT = GetObjectType(obstacle, obstacleType);
  2539.  
  2540.         switch (navigatorOT)
  2541.         {
  2542.         case AIOT_UNKNOWN:
  2543.         case AIOT_PLAYER:
  2544.                 return NI_IGNORE;
  2545.         case AIOT_AGENTSMALL:
  2546.                 // don't navigate around their enemies, unless the enemy is bigger
  2547.                 /*    if (enemy)
  2548.                       return obstacleOT > navigatorOT ? NI_STEER : NI_IGNORE;
  2549.                     else*/
  2550.                 return NI_STEER;
  2551.         case AIOT_AGENTMED:
  2552.         case AIOT_AGENTBIG:
  2553.                 // don't navigate around their enemies, unless the enemy is same size or bigger
  2554.                 if (enemy)
  2555.                         return obstacleOT >= navigatorOT ? NI_STEER : NI_IGNORE;
  2556.                 else
  2557.                         return NI_STEER;
  2558.         default:
  2559.                 AIError("GetNavInteraction: Unhandled switch case %d", navigatorOT);
  2560.                 return NI_IGNORE;
  2561.         }
  2562. }
  2563.  
  2564. void CAIActor::CoordinationEntered(const char* signalName)
  2565. {
  2566.         ++m_activeCoordinationCount;
  2567.         assert(m_activeCoordinationCount < 10);
  2568.  
  2569.         SetSignal(AISIGNAL_ALLOW_DUPLICATES, signalName);
  2570. }
  2571.  
  2572. void CAIActor::CoordinationExited(const char* signalName)
  2573. {
  2574.         //assert(m_activeCoordinationCount < 10 && m_activeCoordinationCount > 0);
  2575.         // Morgan - 10-28-10 This should not require a check against zero.
  2576.         // If its already zero, then coordinations were stopped, that had already actors who had finished their roles.
  2577.         // Need addition to coordination system to prevent stop methods being called for already complete sequences.
  2578.         if (m_activeCoordinationCount > 0)
  2579.         {
  2580.                 --m_activeCoordinationCount;
  2581.         }
  2582.  
  2583.         if (m_activeCoordinationCount == 0)
  2584.                 SetSignal(AISIGNAL_ALLOW_DUPLICATES, signalName);
  2585. }
  2586.  
  2587. bool CAIActor::GetInitialPosition(Vec3& initialPosition) const
  2588. {
  2589.         if (m_initialPosition.isValid)
  2590.         {
  2591.                 initialPosition = m_initialPosition.pos;
  2592.                 return true;
  2593.         }
  2594.         else
  2595.         {
  2596.                 return false;
  2597.         }
  2598. }
  2599.  
  2600. void CAIActor::StartBehaviorTree(const char* behaviorName)
  2601. {
  2602.         if (GetAISystem()->GetIBehaviorTreeManager()->StartModularBehaviorTree(GetEntityID(), behaviorName))
  2603.                 m_runningBehaviorTree = true;
  2604. }
  2605.  
  2606. void CAIActor::StopBehaviorTree()
  2607. {
  2608.         if (m_runningBehaviorTree)
  2609.         {
  2610.                 GetAISystem()->GetIBehaviorTreeManager()->StopModularBehaviorTree(GetEntityID());
  2611.                 m_runningBehaviorTree = false;
  2612.         }
  2613. }
  2614.  
  2615. bool CAIActor::IsRunningBehaviorTree() const
  2616. {
  2617.         return m_runningBehaviorTree;
  2618. }
  2619.  
downloadAIActor.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