BVB Source Codes

CRYENGINE Show TargetTrackManager.cpp Source code

Return Download CRYENGINE: download TargetTrackManager.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. /*************************************************************************
  4.    -------------------------------------------------------------------------
  5.    $Id$
  6.    $DateTime$
  7.    Description: Contains and updates all target tracks owned by agents used
  8.         for target selection
  9.  
  10.    -------------------------------------------------------------------------
  11.    History:
  12.    - 02:01:2010: Created by Kevin Kirst
  13.  
  14. *************************************************************************/
  15.  
  16. #include "StdAfx.h"
  17. #include "TargetTrackManager.h"
  18. #include "TargetTrackGroup.h"
  19. #include "TargetTrack.h"
  20. #include "TargetTrackModifiers.h"
  21. #include "ObjectContainer.h"
  22.  
  23. #include <CryAISystem/IAgent.h>
  24. #include "Puppet.h"
  25. #include <CryString/StringUtils.h>
  26.  
  27. #ifdef TARGET_TRACK_DEBUG
  28.         #include "DebugDrawContext.h"
  29. #endif //TARGET_TRACK_DEBUG
  30.  
  31. //#pragma optimize("", off)
  32. //#pragma inline_depth(0)
  33.  
  34. static const uint32 g_uTargetStimulusConfig_Version = 1;
  35. static const char* g_szTargetStimulusConfig_XmlPath = "Libs/AITargetStimulusConfig.xml";
  36. static const uint32 g_uTargetTracksPoolListSize = 16;
  37.  
  38. namespace TargetTrackHelpers
  39. {
  40. const char* GetSoundStimulusNameFromType(const int stimulusType)
  41. {
  42.         static const char* s_soundStimulusNames[AISOUND_LAST] =
  43.         {
  44.                 "SoundGeneric",       // AISOUND_GENERIC
  45.                 "SoundCollision",     // AISOUND_COLLISION
  46.                 "SoundCollisionLoud", // AISOUND_COLLISION_LOUD
  47.                 "SoundMovement",      // AISOUND_MOVEMENT
  48.                 "SoundMovementLoud",  // AISOUND_MOVEMENT_LOUD
  49.                 "SoundWeapon",        // AISOUND_WEAPON
  50.                 "SoundExplosion",     // AISOUND_EXPLOSION
  51.         };
  52.  
  53.         if (stimulusType >= 0 && stimulusType < AISOUND_LAST)
  54.         {
  55.                 return s_soundStimulusNames[stimulusType];
  56.         }
  57.         else
  58.         {
  59.                 CRY_ASSERT_MESSAGE(0, "CTargetTrackManager::TranslateSoundStimulus Unhandled sound stimulus type");
  60.                 return "Unknown";
  61.         }
  62. };
  63.  
  64. //////////////////////////////////////////////////////////////////////////
  65. void ApplyAudioPerceptionScalingParameters(const CPuppet* pPuppet, float& fSoundThreatLevel)
  66. {
  67.         // Attenuate by perception parameter scaling.
  68.         const AgentParameters& parameters = pPuppet->GetParameters();
  69.         const float fGlobalAudioPerceptionScale = gEnv->pAISystem->GetGlobalAudioScale(pPuppet);
  70.         const float complessiveSoundScale = parameters.m_PerceptionParams.audioScale * parameters.m_PerceptionParams.perceptionScale.audio * fGlobalAudioPerceptionScale;
  71.         fSoundThreatLevel *= complessiveSoundScale;
  72. }
  73.  
  74. //////////////////////////////////////////////////////////////////////////
  75. void ApplyVisualPerceptionScalingParameters(const CPuppet* pPuppet, float& fVisualScale)
  76. {
  77.         // Attenuate by perception parameter scaling.
  78.         const AgentParameters& parameters = pPuppet->GetParameters();
  79.         const float fGlobalVisualPerceptionScale = gEnv->pAISystem->GetGlobalVisualScale(pPuppet);
  80.         const float complessiveVisualScale = parameters.m_PerceptionParams.perceptionScale.audio * fGlobalVisualPerceptionScale;
  81.         fVisualScale *= complessiveVisualScale;
  82. }
  83.  
  84. //////////////////////////////////////////////////////////////////////////
  85. EAITargetThreat TranslateTargetThreatFromThreatValue(float fStimulusThreatLevel, float fPuppetDistanceFromEvent, float fEventRadius)
  86. {
  87.         EAITargetThreat targetThreat = AITHREAT_NONE;
  88.         if (fStimulusThreatLevel > FLT_EPSILON && fPuppetDistanceFromEvent <= fEventRadius)
  89.         {
  90.                 if (fStimulusThreatLevel > PERCEPTION_AGGRESSIVE_THR)
  91.                 {
  92.                         targetThreat = AITHREAT_AGGRESSIVE;
  93.                 }
  94.                 else if (fStimulusThreatLevel > PERCEPTION_THREATENING_THR)
  95.                 {
  96.                         targetThreat = AITHREAT_THREATENING;
  97.                 }
  98.                 else if (fStimulusThreatLevel > PERCEPTION_INTERESTING_THR)
  99.                 {
  100.                         targetThreat = AITHREAT_INTERESTING;
  101.                 }
  102.                 else if (fStimulusThreatLevel > PERCEPTION_SUSPECT_THR)
  103.                 {
  104.                         targetThreat = AITHREAT_SUSPECT;
  105.                 }
  106.         }
  107.  
  108.         return targetThreat;
  109. }
  110.  
  111. EAITargetThreat GetSoundStimulusThreatForNonPuppetEntities(const int soundType)
  112. {
  113.         assert(soundType > 0 && soundType < AISOUND_LAST);
  114.  
  115.         if (soundType > 0 && soundType < AISOUND_LAST)
  116.         {
  117.                 static EAITargetThreat s_eSoundStimulusThreat[AISOUND_LAST] =
  118.                 {
  119.                         AITHREAT_INTERESTING,   // AISOUND_GENERIC
  120.                         AITHREAT_INTERESTING,   // AISOUND_COLLISION
  121.                         AITHREAT_THREATENING,   // AISOUND_COLLISION_LOUD
  122.                         AITHREAT_INTERESTING,   // AISOUND_MOVEMENT
  123.                         AITHREAT_THREATENING,   // AISOUND_MOVEMENT_LOUD
  124.                         AITHREAT_THREATENING,   // AISOUND_WEAPON
  125.                         AITHREAT_THREATENING,   // AISOUND_EXPLOSION
  126.                 };
  127.  
  128.                 return s_eSoundStimulusThreat[soundType];
  129.         }
  130.  
  131.         return AITHREAT_NONE;
  132. }
  133.  
  134. //////////////////////////////////////////////////////////////////////////
  135. bool ShouldVisualStimulusBeHandled(tAIObjectID objectID, const Vec3 eventPosition)
  136. {
  137.         if (gAIEnv.CVars.IgnoreVisualStimulus != 0)
  138.                 return false;
  139.  
  140.         CWeakRef<CAIObject> refObject = gAIEnv.pObjectContainer->GetWeakRef(objectID);
  141.         assert(refObject.IsValid());
  142.  
  143.         CPuppet* pPuppet = CastToCPuppetSafe(refObject.GetAIObject());
  144.         if (pPuppet)
  145.         {
  146.                 float fVisualPerceptionScale = 1.0f;   // The default value is 1.0f that will not apply any scaling
  147.                 ApplyVisualPerceptionScalingParameters(pPuppet, fVisualPerceptionScale);
  148.                 const AgentParameters& parameters = pPuppet->GetParameters();
  149.  
  150.                 if (parameters.m_bAiIgnoreFgNode || fVisualPerceptionScale <= .0f)
  151.                         return false;
  152.  
  153.                 const bool isVisualStimulusVisible = pPuppet->IsPointInFOV(eventPosition, fVisualPerceptionScale) != IAIObject::eFOV_Outside;
  154.                 return isVisualStimulusVisible;
  155.         }
  156.  
  157.         return false;
  158. }
  159.  
  160. bool ShouldSoundStimulusBeHandled(tAIObjectID objectID, const Vec3 eventPosition, const float maxSoundDistanceAllowed)
  161. {
  162.         if (gAIEnv.CVars.IgnoreSoundStimulus != 0)
  163.                 return false;
  164.  
  165.         CWeakRef<CAIObject> refObject = gAIEnv.pObjectContainer->GetWeakRef(objectID);
  166.         assert(refObject.IsValid());
  167.  
  168.         CPuppet* pPuppet = CastToCPuppetSafe(refObject.GetAIObject());
  169.         if (pPuppet)
  170.         {
  171.                 float fAudioPerceptionScale = 1.0f;
  172.                 ApplyAudioPerceptionScalingParameters(pPuppet, fAudioPerceptionScale);
  173.                 const AgentParameters& parameters = pPuppet->GetParameters();
  174.  
  175.                 if (parameters.m_bAiIgnoreFgNode || fAudioPerceptionScale <= .0f)
  176.                         return false;
  177.  
  178.                 const Vec3 puppetPosition = pPuppet->GetPos();
  179.                 const float fSoundDistance = puppetPosition.GetDistance(eventPosition) * (1.0f / fAudioPerceptionScale);
  180.                 if (fSoundDistance <= maxSoundDistanceAllowed)
  181.                 {
  182.                         return true;
  183.                 }
  184.         }
  185.  
  186.         return false;
  187. }
  188.  
  189. bool ShouldBulletRainStimulusBeHandled(tAIObjectID objectID)
  190. {
  191.         if (gAIEnv.CVars.IgnoreBulletRainStimulus != 0)
  192.                 return false;
  193.  
  194.         CWeakRef<CAIObject> refObject = gAIEnv.pObjectContainer->GetWeakRef(objectID);
  195.         assert(refObject.IsValid());
  196.  
  197.         CPuppet* pPuppet = CastToCPuppetSafe(refObject.GetAIObject());
  198.         if (pPuppet)
  199.         {
  200.                 const AgentParameters& parameters = pPuppet->GetParameters();
  201.                 return !parameters.m_bAiIgnoreFgNode;
  202.         }
  203.  
  204.         return false;
  205. }
  206.  
  207. bool ShouldGenericStimulusBeHandled(tAIObjectID objectID)
  208. {
  209.         CWeakRef<CAIObject> refObject = gAIEnv.pObjectContainer->GetWeakRef(objectID);
  210.         assert(refObject.IsValid());
  211.  
  212.         CPuppet* pPuppet = CastToCPuppetSafe(refObject.GetAIObject());
  213.         if (pPuppet)
  214.         {
  215.                 const AgentParameters& parameters = pPuppet->GetParameters();
  216.                 return !parameters.m_bAiIgnoreFgNode;
  217.         }
  218.  
  219.         return false;
  220. }
  221.  
  222. //////////////////////////////////////////////////////////////////////////
  223. }
  224.  
  225. //////////////////////////////////////////////////////////////////////////
  226. void CTargetTrackManager::CTargetTrackConfigProxy::ModifyTargetThreat(IAIObject& ownerAI, IAIObject& targetAI, const ITargetTrack& track,
  227.                                                                       float& outThreatRatio, EAITargetThreat& outThreat) const
  228. {
  229.         ITargetTrackThreatModifier* pThreatModifier = m_pManager->GetTargetTrackThreatModifier();
  230.         if (pThreatModifier)
  231.         {
  232.                 pThreatModifier->ModifyTargetThreat(ownerAI, targetAI, track, outThreatRatio, outThreat);
  233.         }
  234. }
  235.  
  236. //////////////////////////////////////////////////////////////////////////
  237. CTargetTrackManager::CTargetTrackManager()
  238.         : m_pThreatModifier()
  239.         , m_pTrackPoolProxy()
  240.         , m_pTrackConfigProxy()
  241. {
  242.         m_pTrackPoolProxy = new CTargetTrackPoolProxy(this);
  243.         assert(m_pTrackPoolProxy);
  244.  
  245.         m_pTrackConfigProxy = new CTargetTrackConfigProxy(this);
  246.         assert(m_pTrackConfigProxy);
  247.  
  248.         PrepareModifiers();
  249.         ResetFreshestTargetData();
  250.  
  251. #ifdef TARGET_TRACK_DEBUG
  252.         m_uLastDebugAgent = 0;
  253. #endif //TARGET_TRACK_DEBUG
  254. }
  255.  
  256. //////////////////////////////////////////////////////////////////////////
  257. CTargetTrackManager::~CTargetTrackManager()
  258. {
  259.         Shutdown();
  260.  
  261.         std::for_each(m_TargetTrackPool.begin(), m_TargetTrackPool.end(), stl::container_object_deleter());
  262.  
  263.         std::for_each(m_Modifiers.begin(), m_Modifiers.end(), stl::container_object_deleter());
  264.  
  265.         SAFE_DELETE(m_pTrackPoolProxy);
  266.         SAFE_DELETE(m_pTrackConfigProxy);
  267. }
  268.  
  269. //////////////////////////////////////////////////////////////////////////
  270. void CTargetTrackManager::PrepareModifiers()
  271. {
  272.         m_Modifiers.reserve(5);
  273.  
  274.         m_Modifiers.push_back(new CTargetTrackDistanceModifier());
  275.         m_Modifiers.push_back(new CTargetTrackHostileModifier());
  276.         m_Modifiers.push_back(new CTargetTrackClassThreatModifier());
  277.         m_Modifiers.push_back(new CTargetTrackDistanceIgnoreModifier());
  278.         m_Modifiers.push_back(new CTargetTrackPlayerModifier());
  279. }
  280.  
  281. //////////////////////////////////////////////////////////////////////////
  282. bool CTargetTrackManager::IsEnabled() const
  283. {
  284.         // Currently based on cvar
  285.         return (gAIEnv.CVars.TargetTracking != 0);
  286. }
  287.  
  288. //////////////////////////////////////////////////////////////////////////
  289. void CTargetTrackManager::SetTargetTrackThreatModifier(ITargetTrackThreatModifier* pModifier)
  290. {
  291.         assert(pModifier);
  292.         m_pThreatModifier = pModifier;
  293. }
  294.  
  295. //////////////////////////////////////////////////////////////////////////
  296. void CTargetTrackManager::ClearTargetTrackThreatModifier()
  297. {
  298.         m_pThreatModifier = NULL;
  299. }
  300.  
  301. //////////////////////////////////////////////////////////////////////////
  302. void CTargetTrackManager::Init()
  303. {
  304.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  305.  
  306.         if (!ReloadConfig())
  307.         {
  308.                 AIWarning("CTargetTrackManager::Init() Warning: Failed to load configuration file \'%s\'", g_szTargetStimulusConfig_XmlPath);
  309.         }
  310. }
  311.  
  312. //////////////////////////////////////////////////////////////////////////
  313. void CTargetTrackManager::Shutdown()
  314. {
  315.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  316.  
  317.         DeleteConfigs();
  318.         DeleteAgents();
  319. }
  320.  
  321. //////////////////////////////////////////////////////////////////////////
  322. void CTargetTrackManager::Reset(IAISystem::EResetReason reason)
  323. {
  324.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  325.  
  326.         switch (reason)
  327.         {
  328.         case IAISystem::RESET_ENTER_GAME:
  329.                 break;
  330.  
  331.         case IAISystem::RESET_LOAD_LEVEL:
  332.                 {
  333.                         if (m_TargetTrackPool.empty())
  334.                         {
  335.                                 m_TargetTrackPool.resize(g_uTargetTracksPoolListSize);
  336.                                 for (uint32 i = 0; i < g_uTargetTracksPoolListSize; ++i)
  337.                                 {
  338.                                         m_TargetTrackPool[i] = new CTargetTrack();
  339.                                 }
  340.                         }
  341.                 }
  342.                 break;
  343.  
  344.         case IAISystem::RESET_UNLOAD_LEVEL:
  345.                 {
  346.                         MEMSTAT_LABEL_SCOPED("CTargetTrackManager::Reset(Unload)");
  347.                         DeleteAgents();
  348.  
  349.                         std::for_each(m_TargetTrackPool.begin(), m_TargetTrackPool.end(), stl::container_object_deleter());
  350.                         stl::free_container(m_TargetTrackPool);
  351.                         stl::free_container(m_ClassThreatValues);
  352.                         ResetFreshestTargetData();
  353.                 }
  354.                 break;
  355.  
  356.         default:
  357.                 // Delete any agents registered
  358.                 DeleteAgents();
  359.                 break;
  360.         }
  361. }
  362.  
  363. //////////////////////////////////////////////////////////////////////////
  364. void CTargetTrackManager::OnObjectRemoved(CAIObject* pObject)
  365. {
  366.         assert(pObject);
  367.  
  368.         if (pObject)
  369.                 UnregisterAgent(pObject->GetAIObjectID());
  370. }
  371.  
  372. //////////////////////////////////////////////////////////////////////////
  373. void CTargetTrackManager::Serialize(TSerialize ser)
  374. {
  375.         ser.BeginGroup("AI_TargetTrackManager");
  376.         {
  377.                 ser.Value("m_ClassThreatValues", m_ClassThreatValues);
  378.  
  379.                 if (ser.IsWriting())
  380.                 {
  381.                         Serialize_Write(ser);
  382.                 }
  383.                 else if (ser.IsReading())
  384.                 {
  385.                         Serialize_Read(ser);
  386.                 }
  387.         }
  388.         ser.EndGroup();
  389. }
  390.  
  391. //////////////////////////////////////////////////////////////////////////
  392. void CTargetTrackManager::Serialize_Write(TSerialize ser)
  393. {
  394.         assert(ser.IsWriting());
  395.  
  396.         int iAgentCount = m_Agents.size();
  397.         ser.Value("iAgentCount", iAgentCount);
  398.  
  399.         TAgentContainer::iterator itAgent = m_Agents.begin();
  400.         TAgentContainer::iterator itAgentEnd = m_Agents.end();
  401.         for (; itAgent != itAgentEnd; ++itAgent)
  402.         {
  403.                 const tAIObjectID agentId = itAgent->first;
  404.                 CTargetTrackGroup* pGroup = itAgent->second;
  405.                 assert(agentId > 0 && pGroup);
  406.  
  407.                 CWeakRef<CAIObject> refAgent = gAIEnv.pObjectContainer->GetWeakRef(agentId);
  408.                 assert(refAgent.IsValid());
  409.  
  410.                 uint32 uConfigHash = pGroup->GetConfigHash();
  411.                 int nTargetLimit = pGroup->GetTargetLimit();
  412.                 assert(uConfigHash > 0);
  413.  
  414.                 ser.BeginGroup("Agent");
  415.                 {
  416.                         refAgent.Serialize(ser);
  417.                         ser.Value("configHash", uConfigHash);
  418.                         ser.Value("targetLimit", nTargetLimit);
  419.  
  420.                         pGroup->Serialize_Write(ser);
  421.                 }
  422.                 ser.EndGroup();
  423.         }
  424. }
  425.  
  426. //////////////////////////////////////////////////////////////////////////
  427. void CTargetTrackManager::Serialize_Read(TSerialize ser)
  428. {
  429.         assert(ser.IsReading());
  430.  
  431.         int iAgentCount = 0;
  432.         ser.Value("iAgentCount", iAgentCount);
  433.  
  434.         DeleteAgents();
  435.  
  436.         for (int iAgent = 0; iAgent < iAgentCount; ++iAgent)
  437.         {
  438.                 CWeakRef<CAIObject> refAgent;
  439.                 uint32 uConfigHash = 0;
  440.                 int nTargetLimit = 0;
  441.  
  442.                 ser.BeginGroup("Agent");
  443.                 {
  444.                         refAgent.Serialize(ser);
  445.                         ser.Value("configHash", uConfigHash);
  446.                         ser.Value("targetLimit", nTargetLimit);
  447.                         assert(refAgent.IsValid() && uConfigHash > 0);
  448.  
  449.                         const tAIObjectID agentId = refAgent.GetObjectID();
  450.                         const bool bRegistered = RegisterAgent(agentId, uConfigHash, nTargetLimit);
  451.                         assert(bRegistered);
  452.                         if (bRegistered)
  453.                         {
  454.                                 TAgentContainer::iterator itAgent = m_Agents.find(agentId);
  455.                                 CTargetTrackGroup* pGroup = (itAgent != m_Agents.end() ? itAgent->second : NULL);
  456.                                 assert(pGroup);
  457.                                 PREFAST_ASSUME(pGroup);
  458.  
  459.                                 pGroup->Serialize_Read(ser);
  460.                         }
  461.                 }
  462.                 ser.EndGroup();
  463.         }
  464. }
  465.  
  466. //////////////////////////////////////////////////////////////////////////
  467. bool CTargetTrackManager::RegisterAgent(tAIObjectID aiObjectId, uint32 uConfigHash, int nTargetLimit)
  468. {
  469.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  470.  
  471.         assert(aiObjectId > 0);
  472.         assert(uConfigHash > 0);
  473.  
  474.         bool bResult = false;
  475.  
  476.         if (aiObjectId > 0)
  477.         {
  478.                 TAgentContainer::const_iterator itAgent = m_Agents.find(aiObjectId);
  479.                 if (itAgent == m_Agents.end())
  480.                 {
  481.                         // Check if configuration exists
  482.                         TConfigContainer::const_iterator itConfig = m_Configs.find(uConfigHash);
  483.                         if (itConfig != m_Configs.end())
  484.                         {
  485.                                 m_Agents[aiObjectId] = new CTargetTrackGroup(m_pTrackPoolProxy, aiObjectId, itConfig->first, nTargetLimit);
  486.                                 bResult = true;
  487.                         }
  488.                 }
  489.         }
  490.  
  491.         return bResult;
  492. }
  493.  
  494. //////////////////////////////////////////////////////////////////////////
  495. bool CTargetTrackManager::RegisterAgent(tAIObjectID aiObjectId, const char* szConfig, int nTargetLimit)
  496. {
  497.         assert(szConfig && szConfig[0]);
  498.  
  499.         const uint32 uConfigHash = GetConfigNameHash(szConfig);
  500.  
  501.         return RegisterAgent(aiObjectId, uConfigHash, nTargetLimit);
  502. }
  503.  
  504. //////////////////////////////////////////////////////////////////////////
  505. bool CTargetTrackManager::UnregisterAgent(tAIObjectID aiObjectId)
  506. {
  507.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  508.  
  509.         assert(aiObjectId > 0);
  510.  
  511.         bool bResult = false;
  512.  
  513.         if (aiObjectId > 0)
  514.         {
  515.                 TAgentContainer::iterator itAgent = m_Agents.find(aiObjectId);
  516.                 if (itAgent != m_Agents.end())
  517.                 {
  518.                         CTargetTrackGroup* pGroup = itAgent->second;
  519.                         assert(pGroup);
  520.  
  521. #ifdef TARGET_TRACK_DEBUG
  522.                         if (m_uLastDebugAgent > 0 && pGroup->GetConfigHash() == m_uLastDebugAgent)
  523.                                 m_uLastDebugAgent = 0;
  524. #endif //TARGET_TRACK_DEBUG
  525.  
  526.                         SAFE_DELETE(pGroup);
  527.  
  528.                         m_Agents.erase(itAgent);
  529.                         bResult = true;
  530.                 }
  531.         }
  532.  
  533.         return bResult;
  534. }
  535.  
  536. //////////////////////////////////////////////////////////////////////////
  537. bool CTargetTrackManager::ResetAgent(tAIObjectID aiObjectId)
  538. {
  539.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  540.  
  541.         assert(aiObjectId > 0);
  542.  
  543.         bool bResult = false;
  544.  
  545.         if (aiObjectId > 0)
  546.         {
  547.                 TAgentContainer::iterator itAgent = m_Agents.find(aiObjectId);
  548.                 if (itAgent != m_Agents.end())
  549.                 {
  550.                         CTargetTrackGroup* pGroup = itAgent->second;
  551.                         assert(pGroup);
  552.  
  553.                         pGroup->Reset();
  554.                         bResult = true;
  555.                 }
  556.         }
  557.  
  558.         return bResult;
  559. }
  560.  
  561. //////////////////////////////////////////////////////////////////////////
  562. bool CTargetTrackManager::SetAgentEnabled(tAIObjectID aiObjectId, bool bEnable)
  563. {
  564.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  565.  
  566.         assert(aiObjectId > 0);
  567.  
  568.         bool bResult = false;
  569.  
  570.         if (aiObjectId > 0)
  571.         {
  572.                 TAgentContainer::iterator itAgent = m_Agents.find(aiObjectId);
  573.                 if (itAgent != m_Agents.end())
  574.                 {
  575.                         CTargetTrackGroup* pGroup = itAgent->second;
  576.                         assert(pGroup);
  577.  
  578.                         pGroup->SetEnabled(bEnable);
  579.                         bResult = true;
  580.                 }
  581.         }
  582.  
  583.         return bResult;
  584. }
  585.  
  586. //////////////////////////////////////////////////////////////////////////
  587. bool CTargetTrackManager::SetTargetClassThreat(tAIObjectID aiObjectId, float fClassThreat)
  588. {
  589.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  590.  
  591.         assert(aiObjectId > 0);
  592.  
  593.         bool bResult = false;
  594.  
  595.         CWeakRef<CAIObject> refObject = gAIEnv.pObjectContainer->GetWeakRef(aiObjectId);
  596.         if (refObject.IsSet())
  597.         {
  598.                 m_ClassThreatValues[aiObjectId] = fClassThreat;
  599.                 bResult = true;
  600.         }
  601.  
  602.         return bResult;
  603. }
  604.  
  605. //////////////////////////////////////////////////////////////////////////
  606. float CTargetTrackManager::GetTargetClassThreat(tAIObjectID aiObjectId) const
  607. {
  608.         assert(aiObjectId > 0);
  609.  
  610.         float fResult = 1.0f;
  611.  
  612.         TClassThreatContainer::const_iterator itValue = m_ClassThreatValues.find(aiObjectId);
  613.         if (itValue != m_ClassThreatValues.end())
  614.         {
  615.                 fResult = itValue->second;
  616.         }
  617.  
  618.         return fResult;
  619. }
  620.  
  621. //////////////////////////////////////////////////////////////////////////
  622. int CTargetTrackManager::GetTargetLimit(tAIObjectID aiObjectId) const
  623. {
  624.         assert(aiObjectId > 0);
  625.  
  626.         int nResult = gAIEnv.CVars.TargetTracks_GlobalTargetLimit;
  627.  
  628.         TAgentContainer::const_iterator itAgent = m_Agents.find(aiObjectId);
  629.         if (itAgent != m_Agents.end())
  630.         {
  631.                 const CTargetTrackGroup* pGroup = itAgent->second;
  632.                 assert(pGroup);
  633.  
  634.                 const int iGroupTargetLimit = pGroup->GetTargetLimit();
  635.                 nResult = nResult > 0 ? (iGroupTargetLimit > 0 ? min(nResult, iGroupTargetLimit) : nResult) : iGroupTargetLimit;
  636.         }
  637.  
  638.         return max(nResult, 0);
  639. }
  640.  
  641. //////////////////////////////////////////////////////////////////////////
  642. bool CTargetTrackManager::HandleStimulusEventInRange(tAIObjectID aiTargetId, const char* szStimulusName, const TargetTrackHelpers::SStimulusEvent& eventInfo, float fRadius)
  643. {
  644.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  645.  
  646.         bool bResult = false;
  647.  
  648.         assert(szStimulusName && szStimulusName[0]);
  649.  
  650.         if (fRadius > FLT_EPSILON)
  651.         {
  652.                 bResult = true;
  653.                 const float fRadiusSq = fRadius * fRadius;
  654.  
  655.                 TAgentContainer::iterator itAgent = m_Agents.begin();
  656.                 TAgentContainer::iterator itAgentEnd = m_Agents.end();
  657.                 for (; itAgent != itAgentEnd; ++itAgent)
  658.                 {
  659.                         CTargetTrackGroup* pGroup = itAgent->second;
  660.                         assert(pGroup);
  661.  
  662.                         CWeakRef<CAIObject> refObject = gAIEnv.pObjectContainer->GetWeakRef(pGroup->GetAIObjectID());
  663.                         CAIObject* pObject = refObject.GetAIObject();
  664.                         assert(pObject);
  665.  
  666.                         if (pObject && pObject->IsEnabled() && eventInfo.vPos.GetSquaredDistance(pObject->GetPos()) <= fRadiusSq)
  667.                         {
  668.                                 const bool handleStimulus = ShouldStimulusBeHandled(refObject.GetObjectID(), eventInfo, fRadius);
  669.                                 if (!handleStimulus)
  670.                                         continue;
  671.  
  672.                                 TargetTrackHelpers::STargetTrackStimulusEvent stimulusEvent(refObject.GetObjectID(), aiTargetId, szStimulusName, eventInfo);
  673.                                 bResult &= HandleStimulusEvent(pGroup, stimulusEvent);
  674.                         }
  675.                 }
  676.         }
  677.  
  678.         return bResult;
  679. }
  680.  
  681. //////////////////////////////////////////////////////////////////////////
  682. bool CTargetTrackManager::HandleStimulusEventForAgent(tAIObjectID aiAgentId, tAIObjectID aiTargetId, const char* szStimulusName, const TargetTrackHelpers::SStimulusEvent& eventInfo)
  683. {
  684.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  685.  
  686.         bool bResult = false;
  687.  
  688.         assert(aiAgentId > 0);
  689.         assert(szStimulusName && szStimulusName[0]);
  690.  
  691.         if (aiAgentId > 0)
  692.         {
  693.                 TAgentContainer::iterator itAgent = m_Agents.find(aiAgentId);
  694.                 if (itAgent != m_Agents.end())
  695.                 {
  696.                         const bool handleStimulus = ShouldStimulusBeHandled(aiAgentId, eventInfo);
  697.                         if (handleStimulus)
  698.                         {
  699.                                 CTargetTrackGroup* pGroup = itAgent->second;
  700.                                 assert(pGroup);
  701.  
  702.                                 TargetTrackHelpers::STargetTrackStimulusEvent stimulusEvent(aiAgentId, aiTargetId, szStimulusName, eventInfo);
  703.                                 bResult = HandleStimulusEvent(pGroup, stimulusEvent);
  704.                         }
  705.                 }
  706.         }
  707.  
  708.         return bResult;
  709. }
  710.  
  711. //////////////////////////////////////////////////////////////////////////
  712. bool CTargetTrackManager::HandleStimulusFromAIEvent(tAIObjectID aiObjectId, const SAIEVENT* pAIEvent, TargetTrackHelpers::EAIEventStimulusType eType)
  713. {
  714.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  715.  
  716.         bool bResult = false;
  717.  
  718.         assert(aiObjectId > 0);
  719.         assert(pAIEvent);
  720.  
  721.         if (aiObjectId > 0 && pAIEvent)
  722.         {
  723.                 TAgentContainer::iterator itAgent = m_Agents.find(aiObjectId);
  724.                 if (itAgent != m_Agents.end())
  725.                 {
  726.                         CTargetTrackGroup* pGroup = itAgent->second;
  727.                         assert(pGroup);
  728.                         bool successfullyTranslated = false;
  729.                         TargetTrackHelpers::STargetTrackStimulusEvent stimulusEvent(aiObjectId);
  730.                         switch (eType)
  731.                         {
  732.                         case TargetTrackHelpers::eEST_Visual:
  733.                                 {
  734.                                         successfullyTranslated = TranslateVisualStimulusIfCanBeHandled(stimulusEvent, pAIEvent);
  735.                                 }
  736.                                 break;
  737.  
  738.                         case TargetTrackHelpers::eEST_Sound:
  739.                                 {
  740.                                         successfullyTranslated = TranslateSoundStimulusIfCanBeHandled(stimulusEvent, pAIEvent);
  741.                                 }
  742.                                 break;
  743.  
  744.                         case TargetTrackHelpers::eEST_BulletRain:
  745.                                 {
  746.                                         successfullyTranslated = TranslateBulletRainStimulusIfCanBeHandled(stimulusEvent, pAIEvent);
  747.                                 }
  748.                                 break;
  749.  
  750.                         case TargetTrackHelpers::eEST_Generic:
  751.                         default:
  752.                                 CRY_ASSERT_MESSAGE(0, "CTargetTrackManager::HandleStimulusEvent Unhandled AIEvent stimulus type received");
  753.                                 break;
  754.                         }
  755.  
  756.                         if (successfullyTranslated)
  757.                                 bResult = HandleStimulusEvent(pGroup, stimulusEvent);
  758.                 }
  759.         }
  760.  
  761.         return bResult;
  762. }
  763.  
  764. //////////////////////////////////////////////////////////////////////////
  765. bool CTargetTrackManager::ShouldStimulusBeHandled(tAIObjectID aiObjectID, const TargetTrackHelpers::SStimulusEvent& stimulusEvent, const float maxRadius /* = FLT_MAX */)
  766. {
  767.         bool shouldHandleTheStimulus = false;
  768.         switch (stimulusEvent.eStimulusType)
  769.         {
  770.         case TargetTrackHelpers::eEST_Visual:
  771.                 {
  772.                         shouldHandleTheStimulus = TargetTrackHelpers::ShouldVisualStimulusBeHandled(aiObjectID, stimulusEvent.vPos);
  773.                 }
  774.                 break;
  775.  
  776.         case TargetTrackHelpers::eEST_Sound:
  777.                 {
  778.                         shouldHandleTheStimulus = TargetTrackHelpers::ShouldSoundStimulusBeHandled(aiObjectID, stimulusEvent.vPos, maxRadius);
  779.                 }
  780.                 break;
  781.  
  782.         case TargetTrackHelpers::eEST_BulletRain:
  783.                 {
  784.                         shouldHandleTheStimulus = TargetTrackHelpers::ShouldBulletRainStimulusBeHandled(aiObjectID);
  785.                 }
  786.                 break;
  787.  
  788.         case TargetTrackHelpers::eEST_Generic:
  789.         default:
  790.                 {
  791.                         shouldHandleTheStimulus = TargetTrackHelpers::ShouldGenericStimulusBeHandled(aiObjectID);
  792.                 }
  793.                 break;
  794.         }
  795.  
  796.         return shouldHandleTheStimulus;
  797. }
  798.  
  799. //////////////////////////////////////////////////////////////////////////
  800. bool CTargetTrackManager::HandleStimulusEvent(CTargetTrackGroup* pGroup, TargetTrackHelpers::STargetTrackStimulusEvent& stimulusEvent)
  801. {
  802.         bool bResult = false;
  803.  
  804.         assert(pGroup);
  805.  
  806.         if (!pGroup->IsEnabled())
  807.                 return false;
  808.  
  809.         const uint32 uConfigHash = pGroup->GetConfigHash();
  810.         const uint32 uStimulusNameHash = GetStimulusNameHash(stimulusEvent.m_sStimulusName);
  811.  
  812.         if (!CheckConfigUsesStimulus(uConfigHash, uStimulusNameHash))
  813.                 return false;
  814.  
  815.         if (stimulusEvent.m_targetId != 0 && !CheckStimulusHostile(stimulusEvent.m_ownerId, stimulusEvent.m_targetId, uConfigHash, uStimulusNameHash))
  816.                 return false;
  817.  
  818.         return pGroup->HandleStimulusEvent(stimulusEvent, uStimulusNameHash);
  819. }
  820.  
  821. //////////////////////////////////////////////////////////////////////////
  822. bool CTargetTrackManager::TriggerPulse(tAIObjectID aiObjectId, tAIObjectID targetId, const char* szStimulusName,
  823.                                        const char* szPulseName)
  824. {
  825.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  826.  
  827.         bool bResult = false;
  828.  
  829.         assert(aiObjectId > 0);
  830.         assert(szStimulusName && szStimulusName[0]);
  831.         assert(szPulseName && szPulseName[0]);
  832.  
  833.         if (aiObjectId > 0)
  834.         {
  835.                 TAgentContainer::iterator itAgent = m_Agents.find(aiObjectId);
  836.                 if (itAgent != m_Agents.end())
  837.                 {
  838.                         CTargetTrackGroup* pGroup = itAgent->second;
  839.                         assert(pGroup);
  840.  
  841.                         // Look up the stimulus config for processing aid
  842.                         const uint32 uStimulusNameHash = GetStimulusNameHash(szStimulusName);
  843.                         if (CheckConfigUsesStimulus(pGroup->GetConfigHash(), uStimulusNameHash))
  844.                         {
  845.                                 const uint32 uPulseNameHash = GetPulseNameHash(szPulseName);
  846.                                 bResult = pGroup->TriggerPulse(targetId, uStimulusNameHash, uPulseNameHash);
  847.                         }
  848.                 }
  849.         }
  850.  
  851.         return bResult;
  852. }
  853.  
  854. //////////////////////////////////////////////////////////////////////////
  855. tAIObjectID CTargetTrackManager::GetAIObjectId(EntityId entityId)
  856. {
  857.         IEntity* pEntity = entityId ? gEnv->pEntitySystem->GetEntity(entityId) : NULL;
  858.         IAIObject* pAI = pEntity ? pEntity->GetAI() : NULL;
  859.  
  860.         return (pAI ? pAI->GetAIObjectID() : INVALID_AIOBJECTID);
  861. }
  862.  
  863. //////////////////////////////////////////////////////////////////////////
  864. bool CTargetTrackManager::CheckConfigUsesStimulus(uint32 uConfigHash, uint32 uStimulusNameHash) const
  865. {
  866.         assert(uConfigHash > 0);
  867.         assert(uStimulusNameHash > 0);
  868.  
  869.         bool bResult = false;
  870.  
  871.         const TargetTrackHelpers::STargetTrackConfig* pConfig = NULL;
  872.         if (GetTargetTrackConfig(uConfigHash, pConfig))
  873.         {
  874.                 assert(pConfig);
  875.  
  876.                 TargetTrackHelpers::STargetTrackConfig::TStimulusContainer::const_iterator itStimulus = pConfig->m_stimuli.find(uStimulusNameHash);
  877.                 bResult = (itStimulus != pConfig->m_stimuli.end());
  878.         }
  879.  
  880.         return bResult;
  881. }
  882.  
  883. //////////////////////////////////////////////////////////////////////////
  884. bool CTargetTrackManager::CheckStimulusHostile(tAIObjectID aiObjectId, tAIObjectID aiTargetId, uint32 uConfigHash, uint32 uStimulusNameHash) const
  885. {
  886.         assert(aiObjectId > 0);
  887.         assert(uStimulusNameHash > 0);
  888.  
  889.         const TargetTrackHelpers::STargetTrackStimulusConfig* pStimulusConfig = NULL;
  890.         if (GetTargetTrackStimulusConfig(uConfigHash, uStimulusNameHash, pStimulusConfig))
  891.         {
  892.                 if (pStimulusConfig->m_bHostileOnly)
  893.                 {
  894.                         CWeakRef<CAIObject> refObject = gAIEnv.pObjectContainer->GetWeakRef(aiObjectId);
  895.                         CWeakRef<CAIObject> refTarget = gAIEnv.pObjectContainer->GetWeakRef(aiTargetId);
  896.                         assert(refObject.IsValid() && refTarget.IsValid());
  897.  
  898.                         CAIObject* pObject = refObject.GetAIObject();
  899.                         CAIObject* pTarget = refTarget.GetAIObject();
  900.                         return (pObject != NULL) && pTarget && pObject->IsHostile(pTarget);
  901.                 }
  902.                 else
  903.                         return true;
  904.         }
  905.  
  906.         return false;
  907. }
  908.  
  909. //////////////////////////////////////////////////////////////////////////
  910. bool CTargetTrackManager::TranslateVisualStimulusIfCanBeHandled(TargetTrackHelpers::STargetTrackStimulusEvent& stimulusEvent, const SAIEVENT* pAIEvent) const
  911. {
  912.         assert(pAIEvent);
  913.         const Vec3& eventPosition = pAIEvent->vPosition;
  914.         bool handleVisualStimulus = TargetTrackHelpers::ShouldVisualStimulusBeHandled(stimulusEvent.m_ownerId, eventPosition);
  915.  
  916.         if (!handleVisualStimulus)
  917.                 return false;
  918.  
  919.         stimulusEvent.m_eStimulusType = TargetTrackHelpers::eEST_Visual;
  920.         stimulusEvent.m_targetId = GetAIObjectId(pAIEvent->sourceId);
  921.         stimulusEvent.m_vTargetPos = eventPosition;
  922.  
  923.         if (pAIEvent->bFuzzySight)
  924.         {
  925.                 stimulusEvent.m_eTargetThreat = AITHREAT_THREATENING;
  926.                 stimulusEvent.m_sStimulusName = "VisualSecondary";
  927.         }
  928.         else
  929.         {
  930.                 stimulusEvent.m_eTargetThreat = AITHREAT_AGGRESSIVE;
  931.                 stimulusEvent.m_sStimulusName = "VisualPrimary";
  932.         }
  933.  
  934.         return true;
  935. }
  936.  
  937. //////////////////////////////////////////////////////////////////////////
  938. bool CTargetTrackManager::TranslateSoundStimulusIfCanBeHandled(TargetTrackHelpers::STargetTrackStimulusEvent& stimulusEvent, const SAIEVENT* pAIEvent) const
  939. {
  940.         assert(pAIEvent);
  941.  
  942.         bool handleSoundStimulus = TargetTrackHelpers::ShouldSoundStimulusBeHandled(stimulusEvent.m_ownerId, pAIEvent->vPosition, pAIEvent->fThreat);
  943.  
  944.         if (!handleSoundStimulus)
  945.                 return false;
  946.  
  947.         stimulusEvent.m_eStimulusType = TargetTrackHelpers::eEST_Sound;
  948.  
  949.         CWeakRef<CAIObject> refObject = gAIEnv.pObjectContainer->GetWeakRef(stimulusEvent.m_ownerId);
  950.         assert(refObject.IsValid());
  951.  
  952.         CPuppet* pPuppet = CastToCPuppetSafe(refObject.GetAIObject());
  953.         if (pPuppet)
  954.         {
  955.                 // Get descriptor
  956.                 SSoundPerceptionDescriptor sDescriptor;
  957.                 if (!pPuppet->GetSoundPerceptionDescriptor((EAISoundStimType)pAIEvent->nType, sDescriptor))
  958.                         CRY_ASSERT_MESSAGE(0, "Missing Sound Perception Descriptor when handling a sound event");
  959.  
  960.                 float fEventRadius = pAIEvent->fThreat;
  961.                 float fSoundThreatLevel = 0.0f;
  962.                 float fSoundTime = 0.0f;
  963.                 const float fDistanceToEvent = Distance::Point_Point(pAIEvent->vPosition, pPuppet->GetPos());
  964.  
  965.                 // Check minimum distance
  966.                 if (fabsf(sDescriptor.fMinDist) <= FLT_EPSILON || fDistanceToEvent > sDescriptor.fMinDist)
  967.                 {
  968.                         fEventRadius *= sDescriptor.fRadiusScale;
  969.                         const float fDistNorm = (fEventRadius > FLT_EPSILON ? fDistanceToEvent / fEventRadius : 0.0f);
  970.                         fSoundThreatLevel = sDescriptor.fBaseThreat * LinStep(sDescriptor.fLinStepMin, sDescriptor.fLinStepMax, fDistNorm);
  971.                         fSoundTime = sDescriptor.fSoundTime;
  972.                 }
  973.  
  974.                 // Make sure that at max level the value reaches over the threshold.
  975.                 fSoundThreatLevel *= 1.1f;
  976.  
  977.                 TargetTrackHelpers::ApplyAudioPerceptionScalingParameters(pPuppet, fSoundThreatLevel);
  978.  
  979.                 // Skip really quiet sounds or too far away sounds
  980.                 stimulusEvent.m_eTargetThreat = TargetTrackHelpers::TranslateTargetThreatFromThreatValue(fSoundThreatLevel, fDistanceToEvent, fEventRadius);
  981.         }
  982.         else
  983.         {
  984.                 stimulusEvent.m_eTargetThreat = TargetTrackHelpers::GetSoundStimulusThreatForNonPuppetEntities(pAIEvent->nType);
  985.         }
  986.  
  987.         stimulusEvent.m_sStimulusName = TargetTrackHelpers::GetSoundStimulusNameFromType(pAIEvent->nType);
  988.  
  989.         stimulusEvent.m_targetId = GetAIObjectId(pAIEvent->sourceId);
  990.         stimulusEvent.m_vTargetPos = pAIEvent->vPosition;
  991.  
  992.         return true;
  993. }
  994.  
  995. //////////////////////////////////////////////////////////////////////////
  996. bool CTargetTrackManager::TranslateBulletRainStimulusIfCanBeHandled(TargetTrackHelpers::STargetTrackStimulusEvent& stimulusEvent, const SAIEVENT* pAIEvent) const
  997. {
  998.         assert(pAIEvent);
  999.         const bool handleBulletRainStimulus = TargetTrackHelpers::ShouldBulletRainStimulusBeHandled(stimulusEvent.m_ownerId);
  1000.         if (!handleBulletRainStimulus)
  1001.                 return false;
  1002.  
  1003.         stimulusEvent.m_eStimulusType = TargetTrackHelpers::eEST_BulletRain;
  1004.         stimulusEvent.m_eTargetThreat = AITHREAT_AGGRESSIVE;
  1005.         stimulusEvent.m_sStimulusName = "BulletRain";
  1006.  
  1007.         stimulusEvent.m_targetId = GetAIObjectId(pAIEvent->sourceId);
  1008.         stimulusEvent.m_vTargetPos = pAIEvent->vPosition;
  1009.  
  1010.         return true;
  1011. }
  1012.  
  1013. //////////////////////////////////////////////////////////////////////////
  1014. void CTargetTrackManager::Update(tAIObjectID aiObjectId)
  1015. {
  1016.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  1017.  
  1018.         assert(aiObjectId > 0);
  1019.  
  1020.         TAgentContainer::iterator itAgent = m_Agents.find(aiObjectId);
  1021.         if (itAgent != m_Agents.end())
  1022.         {
  1023.                 CTargetTrackGroup* pGroup = itAgent->second;
  1024.                 assert(pGroup);
  1025.  
  1026.                 pGroup->Update(m_pTrackConfigProxy);
  1027.         }
  1028. }
  1029.  
  1030. void CTargetTrackManager::ResetFreshestTargetData()
  1031. {
  1032.         stl::free_container(m_dataPerTarget);
  1033. }
  1034.  
  1035. // Note that target data updating happens across factions and groups
  1036. void CTargetTrackManager::ShareFreshestTargetData()
  1037. {
  1038.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  1039.  
  1040.         // Find the freshest visual stimulus data for each target
  1041.         m_dataPerTarget.clear();
  1042.         m_dataPerTarget.reserve(16);
  1043.         {
  1044.                 TAgentContainer::iterator agentIt = m_Agents.begin();
  1045.                 TAgentContainer::iterator agentEnd = m_Agents.end();
  1046.  
  1047.                 for (; agentIt != agentEnd; ++agentIt)
  1048.                 {
  1049.                         CTargetTrackGroup* group = agentIt->second;
  1050.  
  1051.                         CTargetTrackGroup::TTargetTrackContainer& tracks = group->GetTargetTracks();
  1052.  
  1053.                         CTargetTrackGroup::TTargetTrackContainer::iterator trackIt = tracks.begin();
  1054.                         CTargetTrackGroup::TTargetTrackContainer::iterator trackEnd = tracks.end();
  1055.  
  1056.                         for (; trackIt != trackEnd; ++trackIt)
  1057.                         {
  1058.                                 CTargetTrack* track = trackIt->second;
  1059.  
  1060.                                 CTargetTrack::TStimuliInvocationContainer& invocations = track->GetInvocations();
  1061.  
  1062.                                 CTargetTrack::TStimuliInvocationContainer::iterator invocationIt = invocations.begin();
  1063.                                 CTargetTrack::TStimuliInvocationContainer::iterator invocationEnd = invocations.end();
  1064.  
  1065.                                 for (; invocationIt != invocationEnd; ++invocationIt)
  1066.                                 {
  1067.                                         CTargetTrack::SStimulusInvocation& invocation = invocationIt->second;
  1068.  
  1069.                                         if (invocation.m_eStimulusType == TargetTrackHelpers::eEST_Visual)
  1070.                                         {
  1071.                                                 FreshData& data = m_dataPerTarget[track->GetAIObject().GetObjectID()];
  1072.                                                 const float invokeTime = invocation.m_envelopeData.m_fLastInvokeTime;
  1073.                                                 if (invokeTime > data.timeOfFreshestVisualStimulus)
  1074.                                                 {
  1075.                                                         data.timeOfFreshestVisualStimulus = invokeTime;
  1076.                                                         data.freshestVisualPosition = invocation.m_vLastPos;
  1077.                                                         data.freshestVisualDirection = invocation.m_vLastDir;
  1078.                                                 }
  1079.                                         }
  1080.                                 }
  1081.                         }
  1082.                 }
  1083.         }
  1084.  
  1085.         // Write back the freshest invocation data
  1086.         {
  1087.                 TAgentContainer::iterator agentIt = m_Agents.begin();
  1088.                 TAgentContainer::iterator agentEnd = m_Agents.end();
  1089.  
  1090.                 for (; agentIt != agentEnd; ++agentIt)
  1091.                 {
  1092.                         CTargetTrackGroup* group = agentIt->second;
  1093.                         CTargetTrackGroup::TTargetTrackContainer& tracks = group->GetTargetTracks();
  1094.  
  1095.                         CTargetTrackGroup::TTargetTrackContainer::iterator trackIt = tracks.begin();
  1096.                         CTargetTrackGroup::TTargetTrackContainer::iterator trackEnd = tracks.end();
  1097.  
  1098.                         for (; trackIt != trackEnd; ++trackIt)
  1099.                         {
  1100.                                 CTargetTrack* track = trackIt->second;
  1101.  
  1102.                                 DataPerTarget::iterator dataIt = m_dataPerTarget.find(track->GetAIObject().GetObjectID());
  1103.                                 if (dataIt != m_dataPerTarget.end())
  1104.                                 {
  1105.                                         FreshData& data = dataIt->second;
  1106.  
  1107.                                         CTargetTrack::TStimuliInvocationContainer& invocations = track->GetInvocations();
  1108.  
  1109.                                         CTargetTrack::TStimuliInvocationContainer::iterator invocationIt = invocations.begin();
  1110.                                         CTargetTrack::TStimuliInvocationContainer::iterator invocationEnd = invocations.end();
  1111.  
  1112.                                         for (; invocationIt != invocationEnd; ++invocationIt)
  1113.                                         {
  1114.                                                 CTargetTrack::SStimulusInvocation& invocation = invocationIt->second;
  1115.  
  1116.                                                 if (invocation.m_eStimulusType == TargetTrackHelpers::eEST_Visual)
  1117.                                                 {
  1118.                                                         invocation.m_vLastPos = data.freshestVisualPosition;
  1119.                                                         invocation.m_vLastDir = data.freshestVisualDirection;
  1120.                                                 }
  1121.                                         }
  1122.                                 }
  1123.                         }
  1124.                 }
  1125.         }
  1126. }
  1127.  
  1128. //////////////////////////////////////////////////////////////////////////
  1129. void CTargetTrackManager::PullDownThreatLevel(const tAIObjectID aiObjectIdForTargetTrackGroup, const EAITargetThreat maxAllowedThreat)
  1130. {
  1131.         TAgentContainer::iterator agentIt = m_Agents.begin();
  1132.         TAgentContainer::iterator agentEnd = m_Agents.end();
  1133.  
  1134.         for (; agentIt != agentEnd; ++agentIt)
  1135.         {
  1136.                 CTargetTrackGroup* group = agentIt->second;
  1137.  
  1138.                 if (group->GetAIObjectID() == aiObjectIdForTargetTrackGroup)
  1139.                 {
  1140.                         CTargetTrackGroup::TTargetTrackContainer& tracks = group->GetTargetTracks();
  1141.  
  1142.                         CTargetTrackGroup::TTargetTrackContainer::iterator trackIt = tracks.begin();
  1143.                         CTargetTrackGroup::TTargetTrackContainer::iterator trackEnd = tracks.end();
  1144.  
  1145.                         for (; trackIt != trackEnd; ++trackIt)
  1146.                         {
  1147.                                 CTargetTrack* track = trackIt->second;
  1148.  
  1149.                                 CTargetTrack::TStimuliInvocationContainer& invocations = track->GetInvocations();
  1150.  
  1151.                                 CTargetTrack::TStimuliInvocationContainer::iterator invocationIt = invocations.begin();
  1152.                                 CTargetTrack::TStimuliInvocationContainer::iterator invocationEnd = invocations.end();
  1153.  
  1154.                                 for (; invocationIt != invocationEnd; ++invocationIt)
  1155.                                 {
  1156.                                         CTargetTrack::SStimulusInvocation& invocation = invocationIt->second;
  1157.  
  1158.                                         if (invocation.m_eTargetThreat > maxAllowedThreat)
  1159.                                         {
  1160.                                                 invocation.m_eTargetThreat = maxAllowedThreat;
  1161.                                         }
  1162.                                 }
  1163.                         }
  1164.  
  1165.                         return;
  1166.                 }
  1167.         }
  1168. }
  1169.  
  1170. //////////////////////////////////////////////////////////////////////////
  1171. bool CTargetTrackManager::GetDesiredTarget(tAIObjectID aiObjectId, uint32 uDesiredTargetMethod, CWeakRef<CAIObject>& outTarget, SAIPotentialTarget*& pOutTargetInfo)
  1172. {
  1173.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  1174.  
  1175.         bool bResult = false;
  1176.  
  1177.         assert(aiObjectId > 0);
  1178.         outTarget.Reset();
  1179.  
  1180.         TAgentContainer::iterator itAgent = m_Agents.find(aiObjectId);
  1181.         if (itAgent != m_Agents.end())
  1182.         {
  1183.                 CTargetTrackGroup* pGroup = itAgent->second;
  1184.                 assert(pGroup);
  1185.  
  1186.                 bResult = pGroup->GetDesiredTarget((TargetTrackHelpers::EDesiredTargetMethod)uDesiredTargetMethod, outTarget, pOutTargetInfo);
  1187.         }
  1188.  
  1189.         return bResult;
  1190. }
  1191.  
  1192. //////////////////////////////////////////////////////////////////////////
  1193. uint32 CTargetTrackManager::GetBestTargets(tAIObjectID aiObjectId, uint32 uDesiredTargetMethod,
  1194.                                            tAIObjectID* bestTargets, uint32 maxCount)
  1195. {
  1196.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  1197.  
  1198.         uint32 count = 0;
  1199.  
  1200.         TAgentContainer::iterator itAgent = m_Agents.find(aiObjectId);
  1201.  
  1202.         if (itAgent != m_Agents.end())
  1203.         {
  1204.                 CTargetTrackGroup* pGroup = itAgent->second;
  1205.                 assert(pGroup);
  1206.  
  1207.                 const uint32 MaxTracks = 8;
  1208.                 CTargetTrack* tracks[MaxTracks] = { 0 };
  1209.                 assert(maxCount <= MaxTracks);
  1210.  
  1211.                 uint32 trackCount = pGroup->GetBestTrack((TargetTrackHelpers::EDesiredTargetMethod)uDesiredTargetMethod, tracks,
  1212.                                                          MaxTracks);
  1213.  
  1214.                 for (uint32 i = 0; (i < trackCount) && (count < maxCount); ++i)
  1215.                 {
  1216.                         if (tracks[i])
  1217.                         {
  1218.                                 if (tAIObjectID objectID = tracks[i]->GetAITarget().GetObjectID())
  1219.                                         bestTargets[count++] = objectID;
  1220.                         }
  1221.                 }
  1222.         }
  1223.  
  1224.         return count;
  1225. }
  1226.  
  1227. //////////////////////////////////////////////////////////////////////////
  1228. int CTargetTrackManager::GetDesiredTargetCount(tAIObjectID aiTargetId, tAIObjectID aiIgnoreId) const
  1229. {
  1230.         assert(aiTargetId > 0);
  1231.  
  1232.         int iCount = 0;
  1233.  
  1234.         TAgentContainer::const_iterator itAgent = m_Agents.begin();
  1235.         TAgentContainer::const_iterator itAgentEnd = m_Agents.end();
  1236.         for (; itAgent != itAgentEnd; ++itAgent)
  1237.         {
  1238.                 const CTargetTrackGroup* pGroup = itAgent->second;
  1239.                 assert(pGroup);
  1240.  
  1241.                 if (pGroup->GetAIObjectID() != aiIgnoreId && pGroup->IsDesiredTarget(aiTargetId))
  1242.                         ++iCount;
  1243.         }
  1244.  
  1245.         return iCount;
  1246. }
  1247.  
  1248. //////////////////////////////////////////////////////////////////////////
  1249. int CTargetTrackManager::GetPotentialTargetCount(tAIObjectID aiTargetId, tAIObjectID aiIgnoreId) const
  1250. {
  1251.         assert(aiTargetId > 0);
  1252.  
  1253.         int iCount = 0;
  1254.  
  1255.         TAgentContainer::const_iterator itAgent = m_Agents.begin();
  1256.         TAgentContainer::const_iterator itAgentEnd = m_Agents.end();
  1257.         for (; itAgent != itAgentEnd; ++itAgent)
  1258.         {
  1259.                 const CTargetTrackGroup* pGroup = itAgent->second;
  1260.                 assert(pGroup);
  1261.  
  1262.                 if (pGroup->GetAIObjectID() != aiIgnoreId && pGroup->IsPotentialTarget(aiTargetId))
  1263.                         ++iCount;
  1264.         }
  1265.  
  1266.         return iCount;
  1267. }
  1268.  
  1269. //////////////////////////////////////////////////////////////////////////
  1270. int CTargetTrackManager::GetPotentialTargetCountFromFaction(tAIObjectID aiTargetId, const char* factionName, tAIObjectID aiIgnoreId) const
  1271. {
  1272.         assert(aiTargetId > 0);
  1273.  
  1274.         int iCount = 0;
  1275.         const uint8 factionID = gAIEnv.pFactionMap->GetFactionID(factionName);
  1276.  
  1277.         TAgentContainer::const_iterator itAgent = m_Agents.begin();
  1278.         TAgentContainer::const_iterator itAgentEnd = m_Agents.end();
  1279.         for (; itAgent != itAgentEnd; ++itAgent)
  1280.         {
  1281.                 const CTargetTrackGroup* pGroup = itAgent->second;
  1282.                 assert(pGroup);
  1283.  
  1284.                 if (pGroup->GetAIObjectID() != aiIgnoreId && pGroup->IsPotentialTarget(aiTargetId))
  1285.                 {
  1286.                         CAIActor* pTargetActor = CastToCAIActorSafe(gAIEnv.pObjectContainer->GetAIObject(pGroup->GetAIObjectID()));
  1287.                         if ((pTargetActor != NULL) && pTargetActor->GetFactionID() == factionID)
  1288.                                 ++iCount;
  1289.                 }
  1290.         }
  1291.  
  1292.         return iCount;
  1293. }
  1294.  
  1295. //////////////////////////////////////////////////////////////////////////
  1296. CTargetTrack* CTargetTrackManager::GetUnusedTargetTrackFromPool()
  1297. {
  1298.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  1299.  
  1300.         CTargetTrack* pTrack = NULL;
  1301.  
  1302.         if (!m_TargetTrackPool.empty())
  1303.         {
  1304.                 pTrack = *m_TargetTrackPool.rbegin();
  1305.                 m_TargetTrackPool.pop_back();
  1306.         }
  1307.         else
  1308.         {
  1309.                 pTrack = new CTargetTrack();
  1310.         }
  1311.  
  1312.         return pTrack;
  1313. }
  1314.  
  1315. //////////////////////////////////////////////////////////////////////////
  1316. void CTargetTrackManager::AddTargetTrackToPool(CTargetTrack* pTrack)
  1317. {
  1318.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  1319.  
  1320.         assert(pTrack);
  1321.  
  1322.         if (pTrack)
  1323.         {
  1324.                 pTrack->ResetForPool();
  1325.  
  1326.                 if (m_TargetTrackPool.capacity())
  1327.                 {
  1328.                         // Only return the track to the pool whilst the pool is active.
  1329.                         m_TargetTrackPool.push_back(pTrack);
  1330.                 }
  1331.                 else
  1332.                 {
  1333.                         delete pTrack;
  1334.                 }
  1335.         }
  1336. }
  1337.  
  1338. //////////////////////////////////////////////////////////////////////////
  1339. bool CTargetTrackManager::GetTargetTrackConfig(uint32 uNameHash, TargetTrackHelpers::STargetTrackConfig const*& pOutConfig) const
  1340. {
  1341.         assert(uNameHash > 0);
  1342.  
  1343.         bool bResult = false;
  1344.  
  1345.         TConfigContainer::const_iterator itConfig = m_Configs.find(uNameHash);
  1346.         if (itConfig != m_Configs.end())
  1347.         {
  1348.                 pOutConfig = itConfig->second;
  1349.                 assert(pOutConfig);
  1350.  
  1351.                 bResult = true;
  1352.         }
  1353.  
  1354.         return bResult;
  1355. }
  1356.  
  1357. //////////////////////////////////////////////////////////////////////////
  1358. bool CTargetTrackManager::GetTargetTrackStimulusConfig(uint32 uNameHash, uint32 uStimulusHash, TargetTrackHelpers::STargetTrackStimulusConfig const*& pOutConfig) const
  1359. {
  1360.         assert(uNameHash > 0);
  1361.         assert(uStimulusHash > 0);
  1362.  
  1363.         bool bResult = false;
  1364.  
  1365.         const TargetTrackHelpers::STargetTrackConfig* pConfig = NULL;
  1366.         if (GetTargetTrackConfig(uNameHash, pConfig))
  1367.         {
  1368.                 TargetTrackHelpers::STargetTrackConfig::TStimulusContainer::const_iterator itStimulus = pConfig->m_stimuli.find(uStimulusHash);
  1369.                 if (itStimulus != pConfig->m_stimuli.end())
  1370.                 {
  1371.                         pOutConfig = &(itStimulus->second);
  1372.                         bResult = true;
  1373.                 }
  1374.         }
  1375.  
  1376.         return bResult;
  1377. }
  1378.  
  1379. //////////////////////////////////////////////////////////////////////////
  1380. const ITargetTrackModifier* CTargetTrackManager::GetTargetTrackModifier(uint32 uId) const
  1381. {
  1382.         ITargetTrackModifier* pResult = NULL;
  1383.  
  1384.         TModifierContainer::const_iterator itMod = m_Modifiers.begin();
  1385.         TModifierContainer::const_iterator itModEnd = m_Modifiers.end();
  1386.         for (; itMod != itModEnd; ++itMod)
  1387.         {
  1388.                 ITargetTrackModifier* pMod = *itMod;
  1389.                 assert(pMod);
  1390.  
  1391.                 if (pMod && pMod->GetUniqueId() == uId)
  1392.                 {
  1393.                         pResult = pMod;
  1394.                         break;
  1395.                 }
  1396.         }
  1397.  
  1398.         return pResult;
  1399. }
  1400.  
  1401. //////////////////////////////////////////////////////////////////////////
  1402. void CTargetTrackManager::DeleteConfigs()
  1403. {
  1404.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  1405.  
  1406.         TConfigContainer::iterator itConfig = m_Configs.begin();
  1407.         TConfigContainer::iterator itConfigEnd = m_Configs.end();
  1408.         for (; itConfig != itConfigEnd; ++itConfig)
  1409.         {
  1410.                 TargetTrackHelpers::STargetTrackConfig* pConfig = itConfig->second;
  1411.                 SAFE_DELETE(pConfig);
  1412.         }
  1413.         m_Configs.clear();
  1414. }
  1415.  
  1416. //////////////////////////////////////////////////////////////////////////
  1417. void CTargetTrackManager::DeleteAgents()
  1418. {
  1419.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  1420.  
  1421.         TAgentContainer::iterator itAgent = m_Agents.begin();
  1422.         TAgentContainer::iterator itAgentEnd = m_Agents.end();
  1423.         for (; itAgent != itAgentEnd; ++itAgent)
  1424.         {
  1425.                 CTargetTrackGroup* pGroup = itAgent->second;
  1426.                 assert(pGroup);
  1427.  
  1428.                 SAFE_DELETE(pGroup);
  1429.         }
  1430.         m_Agents.clear();
  1431.  
  1432. #ifdef TARGET_TRACK_DEBUG
  1433.         m_uLastDebugAgent = 0;
  1434. #endif //TARGET_TRACK_DEBUG
  1435. }
  1436.  
  1437. //////////////////////////////////////////////////////////////////////////
  1438. bool CTargetTrackManager::ReloadConfig()
  1439. {
  1440.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  1441.  
  1442.         bool bResult = false;
  1443.  
  1444.         // Remove the old configurations
  1445.         DeleteConfigs();
  1446.  
  1447.         XmlNodeRef pRoot = gEnv->pSystem->LoadXmlFromFile(g_szTargetStimulusConfig_XmlPath);
  1448.         if (pRoot && !stricmp(pRoot->getTag(), "AITargetStimulusConfig"))
  1449.         {
  1450.                 // Check version
  1451.                 uint32 uVersion = 0;
  1452.                 if (!pRoot->getAttr("version", uVersion) || uVersion < g_uTargetStimulusConfig_Version)
  1453.                 {
  1454.                         AIWarning("CTargetTrackManager::ReloadConfig() Warning: Invalid version for configuration file \'%s\'", g_szTargetStimulusConfig_XmlPath);
  1455.                 }
  1456.                 else
  1457.                 {
  1458.                         bResult = LoadConfigs(pRoot);
  1459.                         bResult &= ApplyStimulusTemplates();
  1460.                 }
  1461.         }
  1462.  
  1463.         return bResult;
  1464. }
  1465.  
  1466. //////////////////////////////////////////////////////////////////////////
  1467. bool CTargetTrackManager::LoadConfigs(XmlNodeRef& pRoot)
  1468. {
  1469.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  1470.  
  1471.         bool bResult = true;
  1472.  
  1473.         const int iChildCount = (pRoot ? pRoot->getChildCount() : 0);
  1474.         for (int iChild = 0; iChild < iChildCount; ++iChild)
  1475.         {
  1476.                 XmlNodeRef pConfigElement = pRoot->getChild(iChild);
  1477.                 if (!pConfigElement || stricmp(pConfigElement->getTag(), "Config"))
  1478.                         continue;
  1479.  
  1480.                 bool bSuccess = false;
  1481.  
  1482.                 XmlString szName;
  1483.                 if (pConfigElement->getAttr("name", szName) && !szName.empty())
  1484.                 {
  1485.                         TargetTrackHelpers::STargetTrackConfig* pConfig = new TargetTrackHelpers::STargetTrackConfig(szName);
  1486.  
  1487.                         XmlString szTemplate;
  1488.                         if (pConfigElement->getAttr("template", szTemplate) && !szTemplate.empty())
  1489.                         {
  1490.                                 pConfig->m_sTemplate = szTemplate;
  1491.                         }
  1492.                         else
  1493.                         {
  1494.                                 // No template means it's been applied
  1495.                                 pConfig->m_bTemplateApplied = true;
  1496.                         }
  1497.  
  1498.                         XmlNodeRef pStimuliElement = pConfigElement->findChild("Stimuli");
  1499.                         if (pStimuliElement)
  1500.                         {
  1501.                                 bSuccess = LoadConfigStimuli(pConfig, pStimuliElement, !pConfig->m_bTemplateApplied);
  1502.                         }
  1503.  
  1504.                         // Add to container using hash
  1505.                         if (bSuccess)
  1506.                         {
  1507.                                 const uint32 uHash = GetConfigNameHash(szName);
  1508.                                 TConfigContainer::iterator itConfig = m_Configs.find(uHash);
  1509.                                 if (itConfig != m_Configs.end())
  1510.                                 {
  1511.                                         AIWarning("CTargetTrackManager::LoadConfigs() Warning: Hash clash with config \'%s\'... please use a different name!", szName.c_str());
  1512.                                         SAFE_DELETE(pConfig);
  1513.                                         bSuccess = false;
  1514.                                 }
  1515.                                 else
  1516.                                 {
  1517.                                         m_Configs[uHash] = pConfig;
  1518.                                 }
  1519.                         }
  1520.                 }
  1521.  
  1522.                 if (!bSuccess)
  1523.                 {
  1524.                         AIWarning("CTargetTrackManager::LoadConfigs() Warning: Error while parsing target stimulus configuration \'%s\'", szName.c_str());
  1525.                 }
  1526.  
  1527.                 bResult &= bSuccess;
  1528.         }
  1529.  
  1530.         return bResult;
  1531. }
  1532.  
  1533. //////////////////////////////////////////////////////////////////////////
  1534. bool CTargetTrackManager::LoadConfigStimuli(TargetTrackHelpers::STargetTrackConfig* pConfig, XmlNodeRef& pStimuliElement, bool bHasTemplate)
  1535. {
  1536.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  1537.  
  1538.         assert(pConfig && pStimuliElement);
  1539.  
  1540.         bool bResult = true;
  1541.  
  1542.         const int iChildCount = (pStimuliElement ? pStimuliElement->getChildCount() : 0);
  1543.         for (int iChild = 0; iChild < iChildCount; ++iChild)
  1544.         {
  1545.                 XmlNodeRef pStimulusElement = pStimuliElement->getChild(iChild);
  1546.                 if (!pStimulusElement || stricmp(pStimulusElement->getTag(), "Stimulus"))
  1547.                         continue;
  1548.  
  1549.                 bool bSuccess = false;
  1550.  
  1551.                 XmlString szName;
  1552.                 if (pStimulusElement->getAttr("name", szName) && !szName.empty())
  1553.                 {
  1554.                         float fPeak = 0.0f;
  1555.                         float fAttack = 0.0f;
  1556.                         float fDecay = 0.0f;
  1557.                         float fSustainRatio = 0.0f;
  1558.                         float fRelease = 0.0f;
  1559.                         float fIgnore = 0.0f;
  1560.                         bool bHostileOnly = false;
  1561.  
  1562.                         bool bIsValid = pStimulusElement->getAttr("peak", fPeak);
  1563.                         if (!bIsValid || fPeak <= FLT_EPSILON)
  1564.                         {
  1565.                                 // Can only be invalid if we inherit from our template
  1566.                                 if (bHasTemplate)
  1567.                                 {
  1568.                                         fPeak = TargetTrackHelpers::STargetTrackStimulusConfig::INVALID_VALUE;
  1569.                                         bIsValid = true;
  1570.                                 }
  1571.                                 else
  1572.                                 {
  1573.                                         bIsValid = false;
  1574.                                 }
  1575.                         }
  1576.  
  1577.                         if (bIsValid)
  1578.                         {
  1579.                                 if (!pStimulusElement->getAttr("attack", fAttack))
  1580.                                         fAttack = TargetTrackHelpers::STargetTrackStimulusConfig::INVALID_VALUE;
  1581.                                 if (!pStimulusElement->getAttr("decay", fDecay))
  1582.                                         fDecay = TargetTrackHelpers::STargetTrackStimulusConfig::INVALID_VALUE;
  1583.                                 if (!pStimulusElement->getAttr("sustain", fSustainRatio))
  1584.                                         fSustainRatio = TargetTrackHelpers::STargetTrackStimulusConfig::INVALID_VALUE;
  1585.                                 if (!pStimulusElement->getAttr("release", fRelease))
  1586.                                         fRelease = TargetTrackHelpers::STargetTrackStimulusConfig::INVALID_VALUE;
  1587.                                 if (!pStimulusElement->getAttr("ignore", fIgnore))
  1588.                                         fIgnore = TargetTrackHelpers::STargetTrackStimulusConfig::INVALID_VALUE;
  1589.                                 pStimulusElement->getAttr("hostileOnly", bHostileOnly);
  1590.  
  1591.                                 // Add to container using hash
  1592.                                 const uint32 uHash = GetStimulusNameHash(szName);
  1593.                                 TargetTrackHelpers::STargetTrackConfig::TStimulusContainer::iterator itStimulusDef = pConfig->m_stimuli.find(uHash);
  1594.                                 if (itStimulusDef != pConfig->m_stimuli.end())
  1595.                                 {
  1596.                                         AIWarning("CTargetTrackManager::LoadConfigStimuli() Warning: Hash clash with stimulus \'%s\' in configuration \'%s\'... please use a different name!",
  1597.                                                   szName.c_str(), pConfig->m_sName.c_str());
  1598.                                 }
  1599.                                 else
  1600.                                 {
  1601.                                         TargetTrackHelpers::STargetTrackConfig::TStimulusContainer::value_type stimulusPair(uHash, TargetTrackHelpers::STargetTrackStimulusConfig(szName, bHostileOnly, fPeak, fSustainRatio, fAttack, fDecay, fRelease, fIgnore));
  1602.                                         pConfig->m_stimuli.insert(stimulusPair);
  1603.  
  1604.                                         TargetTrackHelpers::STargetTrackStimulusConfig* pStimulusConfig = &(pConfig->m_stimuli.find(uHash)->second);
  1605.  
  1606.                                         // Load modifiers
  1607.                                         XmlNodeRef pModifiersElement = pStimulusElement->findChild("Modifiers");
  1608.                                         if (pModifiersElement && !LoadConfigModifiers(pStimulusConfig, pModifiersElement))
  1609.                                         {
  1610.                                                 AIWarning("CTargetTrackManager::LoadConfigStimuli() Warning: Failed to load all modifiers for stimulus \'%s\' in configuration \'%s\' - stimulus still loaded", szName.c_str(), pConfig->m_sName.c_str());
  1611.                                         }
  1612.  
  1613.                                         // Load pulses
  1614.                                         XmlNodeRef pPulsesElement = pStimulusElement->findChild("Pulses");
  1615.                                         if (pPulsesElement && !LoadConfigPulses(pStimulusConfig, pPulsesElement))
  1616.                                         {
  1617.                                                 AIWarning("CTargetTrackManager::LoadConfigStimuli() Warning: Failed to load all pulses for stimulus \'%s\' in configuration \'%s\' - stimulus still loaded", szName.c_str(), pConfig->m_sName.c_str());
  1618.                                         }
  1619.  
  1620.                                         // Load threat levels
  1621.                                         XmlNodeRef pReleaseThreatLevelsElement = pStimulusElement->findChild("ReleaseThreatLevels");
  1622.                                         if (pReleaseThreatLevelsElement && !LoadConfigReleaseThreatLevels(pStimulusConfig, pReleaseThreatLevelsElement))
  1623.                                         {
  1624.                                                 AIWarning("CTargetTrackManager::LoadConfigStimuli() Warning: Failed to load all threat levels for stimulus \'%s\' in configuration \'%s\' - stimulus still loaded", szName.c_str(), pConfig->m_sName.c_str());
  1625.                                         }
  1626.  
  1627.                                         bSuccess = true;
  1628.                                 }
  1629.                         }
  1630.                 }
  1631.  
  1632.                 if (!bSuccess)
  1633.                 {
  1634.                         AIWarning("CTargetTrackManager::LoadConfigStimuli() Warning: Error while parsing stimulus \'%s\' in configuration \'%s\'", szName.c_str(), pConfig->m_sName.c_str());
  1635.                 }
  1636.  
  1637.                 bResult &= bSuccess;
  1638.         }
  1639.  
  1640.         return bResult;
  1641. }
  1642.  
  1643. //////////////////////////////////////////////////////////////////////////
  1644. bool CTargetTrackManager::LoadConfigModifiers(TargetTrackHelpers::STargetTrackStimulusConfig* pStimulusConfig, XmlNodeRef& pModifiersElement)
  1645. {
  1646.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  1647.  
  1648.         assert(pStimulusConfig && pModifiersElement);
  1649.  
  1650.         bool bResult = true;
  1651.  
  1652.         const int iChildCount = (pModifiersElement ? pModifiersElement->getChildCount() : 0);
  1653.         for (int iChild = 0; iChild < iChildCount; ++iChild)
  1654.         {
  1655.                 XmlNodeRef pModifierElement = pModifiersElement->getChild(iChild);
  1656.                 if (!pModifierElement)
  1657.                         continue;
  1658.  
  1659.                 bool bSuccess = false;
  1660.                 bool bFoundMod = false;
  1661.  
  1662.                 const char* szModifierTag = pModifierElement->getTag();
  1663.  
  1664.                 TModifierContainer::iterator itModifier = m_Modifiers.begin();
  1665.                 TModifierContainer::iterator itModifierEnd = m_Modifiers.end();
  1666.                 for (; itModifier != itModifierEnd; ++itModifier)
  1667.                 {
  1668.                         ITargetTrackModifier* pModifier = *itModifier;
  1669.                         assert(pModifier);
  1670.  
  1671.                         if (pModifier->IsMatchingTag(szModifierTag))
  1672.                         {
  1673.                                 bFoundMod = true;
  1674.  
  1675.                                 const uint32 uId = pModifier->GetUniqueId();
  1676.                                 float fValue = 1.0f;
  1677.                                 float fLimit = 0.0f;
  1678.  
  1679.                                 if (!pModifierElement->getAttr("value", fValue))
  1680.                                         fValue = 1.0f;
  1681.                                 pModifierElement->getAttr("limit", fLimit);
  1682.  
  1683.                                 TargetTrackHelpers::STargetTrackStimulusConfig::TModifierContainer::iterator itModDef = pStimulusConfig->m_modifiers.find(uId);
  1684.                                 if (itModDef != pStimulusConfig->m_modifiers.end())
  1685.                                 {
  1686.                                         AIWarning("CTargetTrackManager::LoadConfigModifiers() Warning: Redefinition of modifier \'%s\' in stimulus configuration \'%s\'",
  1687.                                                   szModifierTag, pStimulusConfig->m_sStimulus.c_str());
  1688.                                 }
  1689.                                 else
  1690.                                 {
  1691.                                         TargetTrackHelpers::STargetTrackStimulusConfig::TModifierContainer::value_type modPair(uId, TargetTrackHelpers::STargetTrackModifierConfig(uId, fValue, fLimit));
  1692.                                         pStimulusConfig->m_modifiers.insert(modPair);
  1693.                                         bSuccess = true;
  1694.                                 }
  1695.                         }
  1696.                 }
  1697.  
  1698.                 if (!bFoundMod)
  1699.                 {
  1700.                         AIWarning("CTargetTrackManager::LoadConfigModifiers() Warning: No matching modifier with the name \'%s\' in stimulus configuration \'%s\'",
  1701.                                   szModifierTag, pStimulusConfig->m_sStimulus.c_str());
  1702.                 }
  1703.  
  1704.                 bResult &= bSuccess;
  1705.         }
  1706.  
  1707.         return bResult;
  1708. }
  1709.  
  1710. //////////////////////////////////////////////////////////////////////////
  1711. bool CTargetTrackManager::LoadConfigPulses(TargetTrackHelpers::STargetTrackStimulusConfig* pStimulusConfig, XmlNodeRef& pPulsesElement)
  1712. {
  1713.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  1714.  
  1715.         assert(pStimulusConfig && pPulsesElement);
  1716.  
  1717.         bool bResult = true;
  1718.  
  1719.         const int iChildCount = (pPulsesElement ? pPulsesElement->getChildCount() : 0);
  1720.         for (int iChild = 0; iChild < iChildCount; ++iChild)
  1721.         {
  1722.                 XmlNodeRef pPulseElement = pPulsesElement->getChild(iChild);
  1723.                 if (!pPulseElement || stricmp(pPulseElement->getTag(), "Pulse"))
  1724.                         continue;
  1725.  
  1726.                 bool bSuccess = false;
  1727.  
  1728.                 XmlString szName;
  1729.                 if (pPulseElement->getAttr("name", szName) && !szName.empty())
  1730.                 {
  1731.                         float fValue = 0.0f;
  1732.                         float fDuration = 0.0f;
  1733.  
  1734.                         pPulseElement->getAttr("value", fValue);
  1735.                         pPulseElement->getAttr("duration", fDuration);
  1736.  
  1737.                         const uint32 uHash = GetPulseNameHash(szName);
  1738.                         TargetTrackHelpers::STargetTrackStimulusConfig::TPulseContainer::iterator itPulseDef = pStimulusConfig->m_pulses.find(uHash);
  1739.                         if (itPulseDef != pStimulusConfig->m_pulses.end())
  1740.                         {
  1741.                                 AIWarning("CTargetTrackManager::LoadConfigPulses() Warning: Hash clash with pulse \'%s\' in stimulus configuration \'%s\'... please use a different name!",
  1742.                                           szName.c_str(), pStimulusConfig->m_sStimulus.c_str());
  1743.                         }
  1744.                         /*else if (fValue <= FLT_EPSILON || fDuration <= FLT_EPSILON)
  1745.                            {
  1746.                            AIWarning("CTargetTrackManager::LoadConfigPulses() Warning: Invalid values used for pulse \'%s\' in configuration \'%s\'",
  1747.                             szName.c_str(), pStimulusConfig->m_sStimulus.c_str());
  1748.                            }*/
  1749.                         else
  1750.                         {
  1751.                                 TargetTrackHelpers::STargetTrackStimulusConfig::TPulseContainer::value_type pulsePair(uHash, TargetTrackHelpers::STargetTrackPulseConfig(szName, fValue, fDuration));
  1752.                                 pStimulusConfig->m_pulses.insert(pulsePair);
  1753.                                 bSuccess = true;
  1754.                         }
  1755.                 }
  1756.  
  1757.                 bResult &= bSuccess;
  1758.         }
  1759.  
  1760.         return bResult;
  1761. }
  1762.  
  1763. //////////////////////////////////////////////////////////////////////////
  1764. bool CTargetTrackManager::LoadConfigReleaseThreatLevels(TargetTrackHelpers::STargetTrackStimulusConfig* pStimulusConfig, XmlNodeRef& pReleaseThreatLevelsElement)
  1765. {
  1766.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  1767.  
  1768.         assert(pStimulusConfig && pReleaseThreatLevelsElement);
  1769.  
  1770.         bool bResult = true;
  1771.  
  1772.         const int iChildCount = (pReleaseThreatLevelsElement ? pReleaseThreatLevelsElement->getChildCount() : 0);
  1773.         for (int iChild = 0; iChild < iChildCount; ++iChild)
  1774.         {
  1775.                 XmlNodeRef pThreatLevelElement = pReleaseThreatLevelsElement->getChild(iChild);
  1776.                 if (!pThreatLevelElement)
  1777.                         continue;
  1778.  
  1779.                 bool bSuccess = false;
  1780.  
  1781.                 const char* szThreatLevelTag = pThreatLevelElement->getTag();
  1782.                 EAITargetThreat threatLevel = AITHREAT_NONE;
  1783.  
  1784.                 if (!stricmp(szThreatLevelTag, "Aggressive"))
  1785.                 {
  1786.                         threatLevel = AITHREAT_AGGRESSIVE;
  1787.                 }
  1788.                 else if (!stricmp(szThreatLevelTag, "Threatening"))
  1789.                 {
  1790.                         threatLevel = AITHREAT_THREATENING;
  1791.                 }
  1792.                 else if (!stricmp(szThreatLevelTag, "Interesting"))
  1793.                 {
  1794.                         threatLevel = AITHREAT_INTERESTING;
  1795.                 }
  1796.                 else if (!stricmp(szThreatLevelTag, "Suspect"))
  1797.                 {
  1798.                         threatLevel = AITHREAT_SUSPECT;
  1799.                 }
  1800.  
  1801.                 if (threatLevel > AITHREAT_NONE)
  1802.                 {
  1803.                         float fRatio = 0.0f;
  1804.                         pThreatLevelElement->getAttr("ratio", fRatio);
  1805.  
  1806.                         TargetTrackHelpers::STargetTrackStimulusConfig::TThreatLevelContainer::value_type threatPair(threatLevel, fRatio);
  1807.                         pStimulusConfig->m_threatLevels.insert(threatPair);
  1808.  
  1809.                         bSuccess = true;
  1810.                 }
  1811.  
  1812.                 if (!bSuccess)
  1813.                 {
  1814.                         AIWarning("CTargetTrackManager::LoadConfigReleaseThreatLevels() Warning: No matching threat level with the name \'%s\' in stimulus configuration \'%s\'",
  1815.                                   szThreatLevelTag, pStimulusConfig->m_sStimulus.c_str());
  1816.                 }
  1817.  
  1818.                 bResult &= bSuccess;
  1819.         }
  1820.  
  1821.         return bResult;
  1822. }
  1823.  
  1824. //////////////////////////////////////////////////////////////////////////
  1825. bool CTargetTrackManager::ApplyStimulusTemplates()
  1826. {
  1827.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  1828.  
  1829.         bool bResult = true;
  1830.  
  1831.         bool bKeepProcessing = true;
  1832.         while (bKeepProcessing)
  1833.         {
  1834.                 bKeepProcessing = false;
  1835.  
  1836.                 TConfigContainer::iterator itConfig = m_Configs.begin();
  1837.                 TConfigContainer::iterator itConfigEnd = m_Configs.end();
  1838.                 for (; itConfig != itConfigEnd; ++itConfig)
  1839.                 {
  1840.                         TargetTrackHelpers::STargetTrackConfig* pConfig = itConfig->second;
  1841.                         assert(pConfig);
  1842.                         if (!pConfig || pConfig->m_bTemplateApplied)
  1843.                                 continue;
  1844.  
  1845.                         // Find template parent and see if it is ready
  1846.                         const uint32 uTemplateHash = GetConfigNameHash(pConfig->m_sTemplate.c_str());
  1847.                         TConfigContainer::const_iterator itParent = m_Configs.find(uTemplateHash);
  1848.                         if (itParent == m_Configs.end())
  1849.                         {
  1850.                                 AIWarning("CTargetTrackManager::ApplyConfigTemplates() Warning: Configuration \'%s\' is defined to use template \'%s\' which doesn't exist!", pConfig->m_sName.c_str(), pConfig->m_sTemplate.c_str());
  1851.                                 pConfig->m_bTemplateApplied = true;
  1852.                                 continue;
  1853.                         }
  1854.  
  1855.                         const TargetTrackHelpers::STargetTrackConfig* pParent = itParent->second;
  1856.                         assert(pParent);
  1857.                         if (pParent && !pParent->m_bTemplateApplied)
  1858.                         {
  1859.                                 // Parent is not ready, so we need another pass
  1860.                                 bKeepProcessing = true;
  1861.                                 continue;
  1862.                         }
  1863.  
  1864.                         const bool bApplied = ApplyStimulusTemplate(pConfig, pParent);
  1865.                         if (!bApplied)
  1866.                         {
  1867.                                 AIWarning("CTargetTrackManager::ApplyConfigTemplates() Warning: Configuration \'%s\' failed to inherit from \'%s\'", pConfig->m_sName.c_str(), pConfig->m_sTemplate.c_str());
  1868.                         }
  1869.  
  1870.                         bResult &= bApplied;
  1871.                 }
  1872.         }
  1873.  
  1874.         return bResult;
  1875. }
  1876.  
  1877. //////////////////////////////////////////////////////////////////////////
  1878. bool CTargetTrackManager::ApplyStimulusTemplate(TargetTrackHelpers::STargetTrackConfig* pConfig, const TargetTrackHelpers::STargetTrackConfig* pParent)
  1879. {
  1880.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  1881.  
  1882.         bool bResult = false;
  1883.  
  1884.         if (pConfig && pParent)
  1885.         {
  1886.                 assert(pConfig->m_sTemplate.compare(pParent->m_sName) == 0);
  1887.  
  1888.                 // 1. Use values from parent's stimulus definition if config did not define it
  1889.                 TargetTrackHelpers::STargetTrackConfig::TStimulusContainer::iterator itConfigStimulus = pConfig->m_stimuli.begin();
  1890.                 TargetTrackHelpers::STargetTrackConfig::TStimulusContainer::iterator itConfigStimulusEnd = pConfig->m_stimuli.end();
  1891.                 for (; itConfigStimulus != itConfigStimulusEnd; ++itConfigStimulus)
  1892.                 {
  1893.                         TargetTrackHelpers::STargetTrackStimulusConfig& configStimulus = itConfigStimulus->second;
  1894.  
  1895.                         TargetTrackHelpers::STargetTrackConfig::TStimulusContainer::const_iterator itParentStimulus_Copy = pParent->m_stimuli.find(GetStimulusNameHash(configStimulus.m_sStimulus));
  1896.                         if (itParentStimulus_Copy != pParent->m_stimuli.end())
  1897.                         {
  1898.                                 const TargetTrackHelpers::STargetTrackStimulusConfig& parentStimulus = itParentStimulus_Copy->second;
  1899.  
  1900.                                 if (configStimulus.m_fPeak == TargetTrackHelpers::STargetTrackStimulusConfig::INVALID_VALUE)
  1901.                                 {
  1902.                                         configStimulus.m_fPeak = parentStimulus.m_fPeak;
  1903.                                         configStimulus.m_ucInheritanceMask |= TargetTrackHelpers::STargetTrackStimulusConfig::eIM_Peak;
  1904.                                 }
  1905.                                 if (configStimulus.m_fAttack == TargetTrackHelpers::STargetTrackStimulusConfig::INVALID_VALUE)
  1906.                                 {
  1907.                                         configStimulus.m_fAttack = parentStimulus.m_fAttack;
  1908.                                         configStimulus.m_ucInheritanceMask |= TargetTrackHelpers::STargetTrackStimulusConfig::eIM_Attack;
  1909.                                 }
  1910.                                 if (configStimulus.m_fDecay == TargetTrackHelpers::STargetTrackStimulusConfig::INVALID_VALUE)
  1911.                                 {
  1912.                                         configStimulus.m_fDecay = parentStimulus.m_fDecay;
  1913.                                         configStimulus.m_ucInheritanceMask |= TargetTrackHelpers::STargetTrackStimulusConfig::eIM_Decay;
  1914.                                 }
  1915.                                 if (configStimulus.m_fSustainRatio == TargetTrackHelpers::STargetTrackStimulusConfig::INVALID_VALUE)
  1916.                                 {
  1917.                                         configStimulus.m_fSustainRatio = parentStimulus.m_fSustainRatio;
  1918.                                         configStimulus.m_ucInheritanceMask |= TargetTrackHelpers::STargetTrackStimulusConfig::eIM_Sustain;
  1919.                                 }
  1920.                                 if (configStimulus.m_fRelease == TargetTrackHelpers::STargetTrackStimulusConfig::INVALID_VALUE)
  1921.                                 {
  1922.                                         configStimulus.m_fRelease = parentStimulus.m_fRelease;
  1923.                                         configStimulus.m_ucInheritanceMask |= TargetTrackHelpers::STargetTrackStimulusConfig::eIM_Release;
  1924.                                 }
  1925.                                 if (configStimulus.m_fIgnore == TargetTrackHelpers::STargetTrackStimulusConfig::INVALID_VALUE)
  1926.                                 {
  1927.                                         configStimulus.m_fIgnore = parentStimulus.m_fIgnore;
  1928.                                         configStimulus.m_ucInheritanceMask |= TargetTrackHelpers::STargetTrackStimulusConfig::eIM_Ignore;
  1929.                                 }
  1930.  
  1931.                                 // Inherit any undefined modifiers from the parent
  1932.                                 TargetTrackHelpers::STargetTrackStimulusConfig::TModifierContainer::const_iterator itParentMod = parentStimulus.m_modifiers.begin();
  1933.                                 TargetTrackHelpers::STargetTrackStimulusConfig::TModifierContainer::const_iterator itParentModEnd = parentStimulus.m_modifiers.end();
  1934.                                 for (; itParentMod != itParentModEnd; ++itParentMod)
  1935.                                 {
  1936.                                         const TargetTrackHelpers::STargetTrackModifierConfig& parentMod = itParentMod->second;
  1937.  
  1938.                                         TargetTrackHelpers::STargetTrackStimulusConfig::TModifierContainer::const_iterator itConfigMod_Copy = configStimulus.m_modifiers.find(parentMod.m_uId);
  1939.                                         if (itConfigMod_Copy == configStimulus.m_modifiers.end())
  1940.                                         {
  1941.                                                 // Duplicate it
  1942.                                                 TargetTrackHelpers::STargetTrackStimulusConfig::TModifierContainer::value_type modPair(parentMod.m_uId, TargetTrackHelpers::STargetTrackModifierConfig(parentMod, true));
  1943.                                                 configStimulus.m_modifiers.insert(modPair);
  1944.                                         }
  1945.                                 }
  1946.  
  1947.                                 // Inherit any undefined pulses from the parent
  1948.                                 TargetTrackHelpers::STargetTrackStimulusConfig::TPulseContainer::const_iterator itParentPulse = parentStimulus.m_pulses.begin();
  1949.                                 TargetTrackHelpers::STargetTrackStimulusConfig::TPulseContainer::const_iterator itParentPulseEnd = parentStimulus.m_pulses.end();
  1950.                                 for (; itParentPulse != itParentPulseEnd; ++itParentPulse)
  1951.                                 {
  1952.                                         const TargetTrackHelpers::STargetTrackPulseConfig& parentPulse = itParentPulse->second;
  1953.  
  1954.                                         const uint32 uPulseHash = GetPulseNameHash(parentPulse.m_sPulse);
  1955.                                         TargetTrackHelpers::STargetTrackStimulusConfig::TPulseContainer::const_iterator itConfigPulse_Copy = configStimulus.m_pulses.find(uPulseHash);
  1956.                                         if (itConfigPulse_Copy == configStimulus.m_pulses.end())
  1957.                                         {
  1958.                                                 // Duplicate it
  1959.                                                 TargetTrackHelpers::STargetTrackStimulusConfig::TPulseContainer::value_type pulsePair(uPulseHash, TargetTrackHelpers::STargetTrackPulseConfig(parentPulse, true));
  1960.                                                 configStimulus.m_pulses.insert(pulsePair);
  1961.                                         }
  1962.                                 }
  1963.  
  1964.                                 // Inherit any undefined threat levels from the parent
  1965.                                 TargetTrackHelpers::STargetTrackStimulusConfig::TThreatLevelContainer::const_iterator itParentThreatLevel = parentStimulus.m_threatLevels.begin();
  1966.                                 TargetTrackHelpers::STargetTrackStimulusConfig::TThreatLevelContainer::const_iterator itParentThreatLevelEnd = parentStimulus.m_threatLevels.end();
  1967.                                 for (; itParentThreatLevel != itParentThreatLevelEnd; ++itParentThreatLevel)
  1968.                                 {
  1969.                                         TargetTrackHelpers::STargetTrackStimulusConfig::TThreatLevelContainer::const_iterator itThreatLevel_Copy = configStimulus.m_threatLevels.find(itParentThreatLevel->first);
  1970.  
  1971.                                         if (itThreatLevel_Copy == configStimulus.m_threatLevels.end())
  1972.                                         {
  1973.                                                 // Duplicate it
  1974.                                                 TargetTrackHelpers::STargetTrackStimulusConfig::TThreatLevelContainer::value_type threatPair(itParentThreatLevel->first, itParentThreatLevel->second);
  1975.                                                 configStimulus.m_threatLevels.insert(threatPair);
  1976.                                         }
  1977.                                 }
  1978.                         }
  1979.                 }
  1980.  
  1981.                 // 2. Copy stimulus from the parent if the client did not define them
  1982.                 TargetTrackHelpers::STargetTrackConfig::TStimulusContainer::const_iterator itParentStimulus = pParent->m_stimuli.begin();
  1983.                 TargetTrackHelpers::STargetTrackConfig::TStimulusContainer::const_iterator itParentStimulusEnd = pParent->m_stimuli.end();
  1984.                 for (; itParentStimulus != itParentStimulusEnd; ++itParentStimulus)
  1985.                 {
  1986.                         const TargetTrackHelpers::STargetTrackStimulusConfig& parentStimulus = itParentStimulus->second;
  1987.  
  1988.                         const uint32 uStimulusHash = GetStimulusNameHash(parentStimulus.m_sStimulus);
  1989.                         TargetTrackHelpers::STargetTrackConfig::TStimulusContainer::const_iterator itConfigStimulus_New = pConfig->m_stimuli.find(uStimulusHash);
  1990.                         if (itConfigStimulus_New == pConfig->m_stimuli.end())
  1991.                         {
  1992.                                 // Add to container using hash
  1993.                                 TargetTrackHelpers::STargetTrackConfig::TStimulusContainer::value_type stimulusPair(uStimulusHash, TargetTrackHelpers::STargetTrackStimulusConfig(parentStimulus, true));
  1994.                                 pConfig->m_stimuli.insert(stimulusPair);
  1995.                         }
  1996.                 }
  1997.  
  1998.                 pConfig->m_bTemplateApplied = true;
  1999.                 bResult = true;
  2000.         }
  2001.  
  2002.         return bResult;
  2003. }
  2004.  
  2005. //////////////////////////////////////////////////////////////////////////
  2006. uint32 CTargetTrackManager::GetConfigNameHash(const char* sName)
  2007. {
  2008.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  2009.  
  2010.         return CryStringUtils::CalculateHashLowerCase(sName);
  2011. }
  2012.  
  2013. //////////////////////////////////////////////////////////////////////////
  2014. uint32 CTargetTrackManager::GetStimulusNameHash(const char* sStimulusName)
  2015. {
  2016.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  2017.  
  2018.         return CryStringUtils::CalculateHashLowerCase(sStimulusName);
  2019. }
  2020.  
  2021. //////////////////////////////////////////////////////////////////////////
  2022. uint32 CTargetTrackManager::GetPulseNameHash(const char* sPulseName)
  2023. {
  2024.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  2025.  
  2026.         return CryStringUtils::CalculateHashLowerCase(sPulseName);
  2027. }
  2028.  
  2029. //////////////////////////////////////////////////////////////////////////
  2030. void CTargetTrackManager::DebugDraw()
  2031. {
  2032. #ifdef TARGET_TRACK_DEBUG
  2033.         const int nConfigMode = gAIEnv.CVars.TargetTracks_ConfigDebugDraw;
  2034.         const int nTargetMode = gAIEnv.CVars.TargetTracks_TargetDebugDraw;
  2035.         const char* szAgentName = gAIEnv.CVars.TargetTracks_AgentDebugDraw;
  2036.  
  2037.         if (szAgentName && szAgentName[0] && (
  2038.               stricmp(szAgentName, "0") == 0 ||
  2039.               stricmp(szAgentName, "none") == 0
  2040.               ))
  2041.         {
  2042.                 szAgentName = 0;
  2043.         }
  2044.  
  2045.         DebugDrawConfig(nConfigMode);
  2046.         DebugDrawTargets(nTargetMode, szAgentName);
  2047.         DebugDrawAgent(szAgentName);
  2048. #endif //TARGET_TRACK_DEBUG
  2049. }
  2050.  
  2051. #ifdef TARGET_TRACK_DEBUG
  2052. //////////////////////////////////////////////////////////////////////////
  2053. void CTargetTrackManager::DebugDrawConfig(int nMode)
  2054. {
  2055.         if (nMode <= 0)
  2056.                 return;
  2057.  
  2058.         CDebugDrawContext dc;
  2059.         float fColumnX = 1.0f;
  2060.         float fColumnY = 11.0f;
  2061.  
  2062.         const ColorB textCol(255, 255, 255, 255);
  2063.         const ColorB inheritCol(255, 0, 0, 255);
  2064.         const ColorB unusedCol(128, 128, 128, 255);
  2065.  
  2066.         dc->Draw2dLabel(fColumnX, fColumnY, 1.5f, textCol, false, "Target Track Configs: (%" PRISIZE_T ")", m_Configs.size());
  2067.         fColumnY += 20.0f;
  2068.  
  2069.         const string sFilterName = gAIEnv.CVars.TargetTracks_ConfigDebugFilter;
  2070.  
  2071.         TConfigContainer::const_iterator itConfig = m_Configs.begin();
  2072.         TConfigContainer::const_iterator itConfigEnd = m_Configs.end();
  2073.         for (int i = 1; itConfig != itConfigEnd; ++itConfig, ++i)
  2074.         {
  2075.                 const TargetTrackHelpers::STargetTrackConfig* pConfig = itConfig->second;
  2076.                 assert(pConfig);
  2077.  
  2078.                 // Use filter
  2079.                 if (!sFilterName.empty() && sFilterName != "none" && pConfig->m_sName.find(sFilterName) == string::npos)
  2080.                         continue;
  2081.  
  2082.                 // Draw name
  2083.                 dc->Draw2dLabel(fColumnX, fColumnY, 1.5f, textCol, false, "%d. %s", i, pConfig->m_sName.c_str());
  2084.                 fColumnY += 15.0f;
  2085.  
  2086.                 // Draw inheritance
  2087.                 if (!pConfig->m_sTemplate.empty())
  2088.                 {
  2089.                         string sInheritance;
  2090.                         const TargetTrackHelpers::STargetTrackConfig* pParent = pConfig;
  2091.                         while (pParent && !pParent->m_sTemplate.empty())
  2092.                         {
  2093.                                 TConfigContainer::const_iterator itParent = m_Configs.find(GetConfigNameHash(pParent->m_sTemplate));
  2094.                                 pParent = itParent->second;
  2095.                                 if (pParent)
  2096.                                 {
  2097.                                         if (!sInheritance.empty())
  2098.                                         {
  2099.                                                 sInheritance += " <- ";
  2100.                                         }
  2101.                                         sInheritance += pParent->m_sName;
  2102.                                 }
  2103.                         }
  2104.  
  2105.                         dc->Draw2dLabel(fColumnX + 5.0f, fColumnY, 1.2f, inheritCol, false, "Inheritance: %s", sInheritance.c_str());
  2106.                         fColumnY += 15.0f;
  2107.                 }
  2108.  
  2109.                 // Draw stimulus
  2110.                 TargetTrackHelpers::STargetTrackConfig::TStimulusContainer::const_iterator itStimulus = pConfig->m_stimuli.begin();
  2111.                 TargetTrackHelpers::STargetTrackConfig::TStimulusContainer::const_iterator itStimulusEnd = pConfig->m_stimuli.end();
  2112.                 for (; itStimulus != itStimulusEnd; ++itStimulus)
  2113.                 {
  2114.                         const TargetTrackHelpers::STargetTrackStimulusConfig& stimulus = itStimulus->second;
  2115.                         dc->Draw2dLabel(fColumnX + 5.0f, fColumnY, 1.2f, (stimulus.m_ucInheritanceMask > 0 ? inheritCol : textCol), false,
  2116.                                         "Stimulus: %s", stimulus.m_sStimulus.c_str());
  2117.                         fColumnY += 15.0f;
  2118.                         if (nMode > 1)
  2119.                         {
  2120.                                 // Draw the envelope properties of the stimulus
  2121.                                 dc->Draw2dLabel(fColumnX + 10.0f, fColumnY, 1.0f, stimulus.m_ucInheritanceMask & TargetTrackHelpers::STargetTrackStimulusConfig::eIM_Peak ? inheritCol : textCol,
  2122.                                                 false, "Peak: %.3f", stimulus.m_fPeak);
  2123.                                 dc->Draw2dLabel(fColumnX + 80.0f, fColumnY, 1.0f, stimulus.m_fAttack == TargetTrackHelpers::STargetTrackStimulusConfig::INVALID_VALUE ? unusedCol : (stimulus.m_ucInheritanceMask & TargetTrackHelpers::STargetTrackStimulusConfig::eIM_Attack ? inheritCol : textCol),
  2124.                                                 false, "Attack: %.3f", stimulus.m_fAttack);
  2125.                                 dc->Draw2dLabel(fColumnX + 150.0f, fColumnY, 1.0f, stimulus.m_fDecay == TargetTrackHelpers::STargetTrackStimulusConfig::INVALID_VALUE ? unusedCol : (stimulus.m_ucInheritanceMask & TargetTrackHelpers::STargetTrackStimulusConfig::eIM_Decay ? inheritCol : textCol),
  2126.                                                 false, "Decay: %.3f", stimulus.m_fDecay);
  2127.                                 dc->Draw2dLabel(fColumnX + 220.0f, fColumnY, 1.0f, stimulus.m_fSustainRatio == TargetTrackHelpers::STargetTrackStimulusConfig::INVALID_VALUE ? unusedCol : (stimulus.m_ucInheritanceMask & TargetTrackHelpers::STargetTrackStimulusConfig::eIM_Sustain ? inheritCol : textCol),
  2128.                                                 false, "Sustain: %.3f", stimulus.m_fSustainRatio);
  2129.                                 dc->Draw2dLabel(fColumnX + 290.0f, fColumnY, 1.0f, stimulus.m_fRelease == TargetTrackHelpers::STargetTrackStimulusConfig::INVALID_VALUE ? unusedCol : (stimulus.m_ucInheritanceMask & TargetTrackHelpers::STargetTrackStimulusConfig::eIM_Release ? inheritCol : textCol),
  2130.                                                 false, "Release: %.3f", stimulus.m_fRelease);
  2131.                                 dc->Draw2dLabel(fColumnX + 360.0f, fColumnY, 1.0f, stimulus.m_fIgnore == TargetTrackHelpers::STargetTrackStimulusConfig::INVALID_VALUE ? unusedCol : (stimulus.m_ucInheritanceMask & TargetTrackHelpers::STargetTrackStimulusConfig::eIM_Ignore ? inheritCol : textCol),
  2132.                                                 false, "Release: %.3f", stimulus.m_fIgnore);
  2133.                                 fColumnY += 15.0f;
  2134.                         }
  2135.                         if (nMode == 3 || nMode > 4) // i.e., on '3' or '5'+
  2136.                         {
  2137.                                 TargetTrackHelpers::STargetTrackStimulusConfig::TPulseContainer::const_iterator itPulse = stimulus.m_pulses.begin();
  2138.                                 TargetTrackHelpers::STargetTrackStimulusConfig::TPulseContainer::const_iterator itPulseEnd = stimulus.m_pulses.end();
  2139.                                 for (; itPulse != itPulseEnd; ++itPulse)
  2140.                                 {
  2141.                                         const TargetTrackHelpers::STargetTrackPulseConfig& pulse = itPulse->second;
  2142.  
  2143.                                         // Draw the pulses of the stimulus
  2144.                                         dc->Draw2dLabel(fColumnX + 10.0f, fColumnY, 1.0f, pulse.m_bInherited ? inheritCol : textCol, false, "Pulse: %s", pulse.m_sPulse.c_str());
  2145.                                         dc->Draw2dLabel(fColumnX + 150.0f, fColumnY, 1.0f, pulse.m_bInherited ? inheritCol : textCol, false, "Value: %.3f", pulse.m_fValue);
  2146.                                         dc->Draw2dLabel(fColumnX + 220.0f, fColumnY, 1.0f, pulse.m_bInherited ? inheritCol : textCol, false, "Duration: %.3f", pulse.m_fDuration);
  2147.                                         fColumnY += 15.0f;
  2148.                                 }
  2149.                         }
  2150.                         if (nMode >= 4)
  2151.                         {
  2152.                                 TargetTrackHelpers::STargetTrackStimulusConfig::TModifierContainer::const_iterator itMod = stimulus.m_modifiers.begin();
  2153.                                 TargetTrackHelpers::STargetTrackStimulusConfig::TModifierContainer::const_iterator itModEnd = stimulus.m_modifiers.end();
  2154.                                 for (; itMod != itModEnd; ++itMod)
  2155.                                 {
  2156.                                         const TargetTrackHelpers::STargetTrackModifierConfig& modifier = itMod->second;
  2157.                                         const ITargetTrackModifier* pModifier = GetTargetTrackModifier(modifier.m_uId);
  2158.                                         assert(pModifier);
  2159.  
  2160.                                         // Draw the modifiers of the stimulus
  2161.                                         dc->Draw2dLabel(fColumnX + 10.0f, fColumnY, 1.0f, modifier.m_bInherited ? inheritCol : textCol, false, "Modifier: %s", pModifier->GetTag());
  2162.                                         dc->Draw2dLabel(fColumnX + 150.0f, fColumnY, 1.0f, modifier.m_bInherited ? inheritCol : textCol, false, "Value: %.3f", modifier.m_fValue);
  2163.                                         dc->Draw2dLabel(fColumnX + 220.0f, fColumnY, 1.0f, modifier.m_bInherited ? inheritCol : textCol, false, "Limit: %.3f", modifier.m_fLimit);
  2164.                                         fColumnY += 15.0f;
  2165.                                 }
  2166.                         }
  2167.                 }
  2168.  
  2169.                 fColumnY += 10.0f;
  2170.         }
  2171. }
  2172.  
  2173. //////////////////////////////////////////////////////////////////////////
  2174. void CTargetTrackManager::DebugDrawTargets(int nMode, char const* szAgentName)
  2175. {
  2176.         if (nMode <= 0)
  2177.                 return;
  2178.  
  2179.         if (szAgentName && szAgentName[0])
  2180.         {
  2181.                 // Get group for this agent
  2182.                 CAIObject* pAgent = gAIEnv.pAIObjectManager->GetAIObjectByName(szAgentName);
  2183.                 if (pAgent)
  2184.                 {
  2185.                         const tAIObjectID aiObjectId = pAgent->GetAIObjectID();
  2186.                         TAgentContainer::iterator itAgent = m_Agents.find(aiObjectId);
  2187.                         if (itAgent != m_Agents.end())
  2188.                         {
  2189.                                 CTargetTrackGroup* pGroup = itAgent->second;
  2190.                                 assert(pGroup);
  2191.  
  2192.                                 const int nTargetedCount = (nMode == 1
  2193.                                                             ? GetDesiredTargetCount(aiObjectId)
  2194.                                                             : GetPotentialTargetCount(aiObjectId)
  2195.                                                             );
  2196.  
  2197.                                 pGroup->DebugDrawTargets(nMode, nTargetedCount, true);
  2198.                         }
  2199.                 }
  2200.         }
  2201.         else
  2202.         {
  2203.                 TAgentContainer::iterator itAgent = m_Agents.begin();
  2204.                 TAgentContainer::iterator itAgentEnd = m_Agents.end();
  2205.                 for (; itAgent != itAgentEnd; ++itAgent)
  2206.                 {
  2207.                         CTargetTrackGroup* pGroup = itAgent->second;
  2208.                         assert(pGroup);
  2209.  
  2210.                         tAIObjectID aiObjectId = pGroup->GetAIObjectID();
  2211.  
  2212.                         const int nTargetedCount = (nMode == 1
  2213.                                                     ? GetDesiredTargetCount(aiObjectId)
  2214.                                                     : GetPotentialTargetCount(aiObjectId)
  2215.                                                     );
  2216.  
  2217.                         pGroup->DebugDrawTargets(nMode, nTargetedCount);
  2218.                 }
  2219.         }
  2220. }
  2221.  
  2222. //////////////////////////////////////////////////////////////////////////
  2223. void CTargetTrackManager::DebugDrawAgent(char const* szAgentName)
  2224. {
  2225.         const tAIObjectID uLastDebugAgent = m_uLastDebugAgent;
  2226.         m_uLastDebugAgent = 0;
  2227.  
  2228.         if (szAgentName && szAgentName[0])
  2229.         {
  2230.                 // Get group for this agent
  2231.                 CAIObject* pAgent = gAIEnv.pAIObjectManager->GetAIObjectByName(szAgentName);
  2232.                 if (pAgent)
  2233.                 {
  2234.                         const tAIObjectID uAgentObjectId = pAgent->GetAIObjectID();
  2235.                         TAgentContainer::iterator itAgent = m_Agents.find(uAgentObjectId);
  2236.                         if (itAgent != m_Agents.end())
  2237.                         {
  2238.                                 CTargetTrackGroup* pGroup = itAgent->second;
  2239.                                 assert(pGroup);
  2240.  
  2241.                                 pGroup->DebugDrawTracks(m_pTrackConfigProxy, false);
  2242.                                 m_uLastDebugAgent = uAgentObjectId;
  2243.                         }
  2244.                 }
  2245.         }
  2246.  
  2247.         if (m_uLastDebugAgent != uLastDebugAgent && uLastDebugAgent > 0)
  2248.         {
  2249.                 TAgentContainer::iterator itAgent = m_Agents.find(uLastDebugAgent);
  2250.                 if (itAgent != m_Agents.end())
  2251.                 {
  2252.                         CTargetTrackGroup* pGroup = itAgent->second;
  2253.                         assert(pGroup);
  2254.  
  2255.                         pGroup->DebugDrawTracks(m_pTrackConfigProxy, true);
  2256.                 }
  2257.         }
  2258. }
  2259. #endif //TARGET_TRACK_DEBUG
  2260.  
downloadTargetTrackManager.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