BVB Source Codes

CRYENGINE Show CAISystem.cpp Source code

Return Download CRYENGINE: download CAISystem.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. /********************************************************************
  4.    -------------------------------------------------------------------------
  5.    File name:   CAISystem.cpp
  6.    $Id$
  7.    Description:
  8.  
  9.    -------------------------------------------------------------------------
  10.    History:
  11.    - 2001                               : Created by Petar Kotevski
  12.    - 2003                               : Taken over by Kirill Bulatsev
  13.  
  14.  *********************************************************************/
  15.  
  16. #include "StdAfx.h"
  17.  
  18. #include "CAISystem.h"
  19. #include "AILog.h"
  20.  
  21. #include "ScriptBind_AI.h"
  22.  
  23. #include "AIVehicle.h"
  24. #include "AIPlayer.h"
  25. #include "ObjectContainer.h"
  26. #include "CodeCoverageManager.h"
  27. #include "CodeCoverageGUI.h"
  28. #include <CryAISystem/IVisionMap.h>
  29. #include <CryAISystem/HidespotQueryContext.h>
  30. #include <CryAISystem/AISystemListener.h>
  31. #include "PerceptionManager.h"
  32. #include "SmartObjects.h"
  33. #include "CalculationStopper.h"
  34. #include "AIRadialOcclusion.h"
  35. #include "AIActions.h"
  36. #include "GraphNodeManager.h"
  37. #include "FireCommand.h"
  38. #include "CentralInterestManager.h"
  39. #include "TacticalPointSystem/TacticalPointSystem.h"
  40. #include "TargetSelection/TargetTrackManager.h"
  41. #include "Communication/CommunicationManager.h"
  42. #include "Cover/CoverSystem.h"
  43. #include "Navigation/NavigationSystem/NavigationSystem.h"
  44. #include "PathfinderNavigationSystemUser.h"
  45. #include "SelectionTree/SelectionTreeManager.h"
  46. #include "BehaviorTree/BehaviorTreeManager.h"
  47. #include "BehaviorTree/BehaviorTreeNodeRegistration.h"
  48. #include "CollisionAvoidance/CollisionAvoidanceSystem.h"
  49. #include "BehaviorTree/BehaviorTreeGraft.h"
  50. #include <CryAISystem/IMovementSystem.h>
  51. #include "Movement/MovementSystemCreator.h"
  52. #include "Group/GroupManager.h"
  53. #include "Factions/FactionMap.h"
  54. #include "Walkability/WalkabilityCacheManager.h"
  55. #include "DebugDrawContext.h"
  56. #include "FlightNavRegion2.h"
  57. #include "Sequence/SequenceManager.h"
  58. #include "ClusterDetector.h"
  59. #include "SmartPathFollower.h"
  60.  
  61. #include "AIObjectIterators.h"
  62.  
  63. #include <CrySystem/File/CryBufferedFileReader.h>
  64.  
  65. #include "GoalOpFactory.h"
  66. #include "StatsManager.h"
  67. #include "GameSpecific/GoalOp_G02.h"     //TODO move these out of AISystem
  68. #include "GameSpecific/GoalOp_G04.h"     //TODO move these out of AISystem
  69. #include "GameSpecific/GoalOp_Crysis2.h" //TODO move these out of AISystem
  70.  
  71. #ifdef CRYAISYSTEM_DEBUG
  72.         #include "AIBubblesSystem/AIBubblesSystemImpl.h"
  73. #endif
  74.  
  75. #include "Sequence/SequenceFlowNodes.h"
  76. #include "FlyHelpers_TacticalPointLanguageExtender.h"
  77.  
  78. #include <algorithm>  // std::min()
  79.  
  80. FlyHelpers::CTacticalPointLanguageExtender g_flyHelpersTacticalLanguageExtender;
  81.  
  82. // Description:
  83. //       Helper class for declaring fire command descriptors.
  84. template<class T>
  85. class CFireCommandDescBase : public IFireCommandDesc
  86. {
  87. public:
  88.         CFireCommandDescBase(const char* name) : m_name(name) {};
  89.         virtual const char*          GetName()                { return m_name.c_str(); }
  90.         virtual IFireCommandHandler* Create(IAIActor* pOwner) { return new T(pOwner); }
  91.         virtual void                 Release()                { delete this; }
  92.  
  93. protected:
  94.         string m_name;
  95. };
  96. #define CREATE_FIRECOMMAND_DESC(name, type) new CFireCommandDescBase<type>((name))
  97.  
  98. // used to determine if a forbidden area should be rasterised
  99.  
  100. static const size_t AILogMaxIdLen = 32;
  101. static const char* sCodeCoverageContextFile = "ccContext.txt";
  102.  
  103. #define BroadcastToListeners(call)                                       \
  104.   SystemListenerSet::iterator listenerIt = m_setSystemListeners.begin(); \
  105.   SystemListenerSet::iterator listenerEnd = m_setSystemListeners.end();  \
  106.   for (; listenerIt != listenerEnd; ++listenerIt)                        \
  107.   {                                                                      \
  108.     (*listenerIt)->call;                                                 \
  109.   }
  110.  
  111. template<> std::vector<SAIObjectMapIter<CWeakRef>*> SAIObjectMapIter<CWeakRef>::pool = std::vector<SAIObjectMapIter<CWeakRef>*>();
  112. template<> std::vector<SAIObjectMapIterOfType<CWeakRef>*> SAIObjectMapIterOfType<CWeakRef>::pool = std::vector<SAIObjectMapIterOfType<CWeakRef>*>();
  113. template<> std::vector<SAIObjectMapIterInRange<CWeakRef>*> SAIObjectMapIterInRange<CWeakRef>::pool = std::vector<SAIObjectMapIterInRange<CWeakRef>*>();
  114. template<> std::vector<SAIObjectMapIterOfTypeInRange<CWeakRef>*> SAIObjectMapIterOfTypeInRange<CWeakRef>::pool = std::vector<SAIObjectMapIterOfTypeInRange<CWeakRef>*>();
  115. template<> std::vector<SAIObjectMapIterInShape<CWeakRef>*> SAIObjectMapIterInShape<CWeakRef>::pool = std::vector<SAIObjectMapIterInShape<CWeakRef>*>();
  116. template<> std::vector<SAIObjectMapIterOfTypeInShape<CWeakRef>*> SAIObjectMapIterOfTypeInShape<CWeakRef>::pool = std::vector<SAIObjectMapIterOfTypeInShape<CWeakRef>*>();
  117. template<> std::vector<SAIObjectMapIter<CCountedRef>*> SAIObjectMapIter<CCountedRef>::pool = std::vector<SAIObjectMapIter<CCountedRef>*>();
  118. template<> std::vector<SAIObjectMapIterOfType<CCountedRef>*> SAIObjectMapIterOfType<CCountedRef>::pool = std::vector<SAIObjectMapIterOfType<CCountedRef>*>();
  119. template<> std::vector<SAIObjectMapIterInRange<CCountedRef>*> SAIObjectMapIterInRange<CCountedRef>::pool = std::vector<SAIObjectMapIterInRange<CCountedRef>*>();
  120. template<> std::vector<SAIObjectMapIterOfTypeInRange<CCountedRef>*> SAIObjectMapIterOfTypeInRange<CCountedRef>::pool = std::vector<SAIObjectMapIterOfTypeInRange<CCountedRef>*>();
  121. template<> std::vector<SAIObjectMapIterInShape<CCountedRef>*> SAIObjectMapIterInShape<CCountedRef>::pool = std::vector<SAIObjectMapIterInShape<CCountedRef>*>();
  122. template<> std::vector<SAIObjectMapIterOfTypeInShape<CCountedRef>*> SAIObjectMapIterOfTypeInShape<CCountedRef>::pool = std::vector<SAIObjectMapIterOfTypeInShape<CCountedRef>*>();
  123.  
  124. //===================================================================
  125. // ClearAIObjectIteratorPools
  126. //===================================================================
  127. void ClearAIObjectIteratorPools()
  128. {
  129.         // (MATT) Iterators now have their destructors called before they enter the pool - so we only need to free the memory here {2008/12/04}
  130.         std::for_each(SAIObjectMapIter<CWeakRef>::pool.begin(), SAIObjectMapIter<CWeakRef>::pool.end(), DeleteAIObjectMapIter<CWeakRef> );
  131.         std::for_each(SAIObjectMapIterOfType<CWeakRef>::pool.begin(), SAIObjectMapIterOfType<CWeakRef>::pool.end(), DeleteAIObjectMapIter<CWeakRef> );
  132.         std::for_each(SAIObjectMapIterInRange<CWeakRef>::pool.begin(), SAIObjectMapIterInRange<CWeakRef>::pool.end(), DeleteAIObjectMapIter<CWeakRef> );
  133.         std::for_each(SAIObjectMapIterOfTypeInRange<CWeakRef>::pool.begin(), SAIObjectMapIterOfTypeInRange<CWeakRef>::pool.end(), DeleteAIObjectMapIter<CWeakRef> );
  134.         std::for_each(SAIObjectMapIterInShape<CWeakRef>::pool.begin(), SAIObjectMapIterInShape<CWeakRef>::pool.end(), DeleteAIObjectMapIter<CWeakRef> );
  135.         std::for_each(SAIObjectMapIterOfTypeInShape<CWeakRef>::pool.begin(), SAIObjectMapIterOfTypeInShape<CWeakRef>::pool.end(), DeleteAIObjectMapIter<CWeakRef> );
  136.         std::for_each(SAIObjectMapIter<CCountedRef>::pool.begin(), SAIObjectMapIter<CCountedRef>::pool.end(), DeleteAIObjectMapIter<CCountedRef> );
  137.         std::for_each(SAIObjectMapIterOfType<CCountedRef>::pool.begin(), SAIObjectMapIterOfType<CCountedRef>::pool.end(), DeleteAIObjectMapIter<CCountedRef> );
  138.         std::for_each(SAIObjectMapIterInRange<CCountedRef>::pool.begin(), SAIObjectMapIterInRange<CCountedRef>::pool.end(), DeleteAIObjectMapIter<CCountedRef> );
  139.         std::for_each(SAIObjectMapIterOfTypeInRange<CCountedRef>::pool.begin(), SAIObjectMapIterOfTypeInRange<CCountedRef>::pool.end(), DeleteAIObjectMapIter<CCountedRef> );
  140.         std::for_each(SAIObjectMapIterInShape<CCountedRef>::pool.begin(), SAIObjectMapIterInShape<CCountedRef>::pool.end(), DeleteAIObjectMapIter<CCountedRef> );
  141.         std::for_each(SAIObjectMapIterOfTypeInShape<CCountedRef>::pool.begin(), SAIObjectMapIterOfTypeInShape<CCountedRef>::pool.end(), DeleteAIObjectMapIter<CCountedRef> );
  142.         stl::free_container(SAIObjectMapIter<CWeakRef>::pool);
  143.         stl::free_container(SAIObjectMapIterOfType<CWeakRef>::pool);
  144.         stl::free_container(SAIObjectMapIterInRange<CWeakRef>::pool);
  145.         stl::free_container(SAIObjectMapIterOfTypeInRange<CWeakRef>::pool);
  146.         stl::free_container(SAIObjectMapIterInShape<CWeakRef>::pool);
  147.         stl::free_container(SAIObjectMapIterOfTypeInShape<CWeakRef>::pool);
  148.         stl::free_container(SAIObjectMapIter<CCountedRef>::pool);
  149.         stl::free_container(SAIObjectMapIterOfType<CCountedRef>::pool);
  150.         stl::free_container(SAIObjectMapIterInRange<CCountedRef>::pool);
  151.         stl::free_container(SAIObjectMapIterOfTypeInRange<CCountedRef>::pool);
  152.         stl::free_container(SAIObjectMapIterInShape<CCountedRef>::pool);
  153.         stl::free_container(SAIObjectMapIterOfTypeInShape<CCountedRef>::pool);
  154. }
  155.  
  156. void RemoveNonActors(CAISystem::AIActorSet& actorSet)
  157. {
  158.         for (CAISystem::AIActorSet::iterator it = actorSet.begin(); it != actorSet.end(); )
  159.         {
  160.                 IAIObject* pAIObject = it->GetAIObject();
  161.                 CRY_ASSERT_TRACE(pAIObject, ("An AI Actors set contains a null entry for object id %d!", it->GetObjectID()));
  162.  
  163.                 // [AlexMcC|29.06.10] We can't trust that this is an AI Actor, because CWeakRef::GetAIObject()
  164.                 // doesn't do any type checking. If this weakref becomes invalid, then the id is used by another
  165.                 // object (which can happen if we chainload or load a savegame), this might not be an actor anymore.
  166.                 const bool bIsActor = pAIObject ? (pAIObject->CastToCAIActor() != NULL) : false;
  167.                 CRY_ASSERT_MESSAGE(bIsActor, "A non-actor is in an AI actor set!");
  168.  
  169.                 if (pAIObject && bIsActor)
  170.                 {
  171.                         ++it;
  172.                 }
  173.                 else
  174.                 {
  175.                         it = actorSet.erase(it);
  176.                 }
  177.         }
  178. }
  179.  
  180. //====================================================================
  181. // CAISystem
  182. //====================================================================
  183. CAISystem::CAISystem(ISystem* pSystem)
  184.         : m_actorProxyFactory(nullptr)
  185.         , m_groupProxyFactory(nullptr)
  186.         , m_pGraph(nullptr)
  187.         , m_pNavigation(nullptr)
  188.         , m_pAIActionManager(nullptr)
  189.         , m_pSmartObjectManager(nullptr)
  190.         , m_bUpdateSmartObjects(false)
  191.         , m_IsEnabled(true)
  192.         , m_enabledActorsUpdateError(0.0f)
  193.         , m_enabledActorsUpdateHead(0)
  194.         , m_totalActorsUpdateCount(0)
  195.         , m_disabledActorsUpdateError(0.0f)
  196.         , m_disabledActorsHead(0)
  197.         , m_iteratingActorSet(false)
  198.         , m_pScriptAI(nullptr)
  199.         , m_walkabilityGeometryBox(nullptr)
  200.         , m_DEBUG_screenFlash(0.0f)
  201.         , m_bCodeCoverageFailed(false)
  202.         , m_nTickCount(0)
  203.         , m_bInitialized(false)
  204.         , m_frameDeltaTime(0.0f)
  205.         , m_frameStartTimeSeconds(0.0f)
  206.         , m_lastVisBroadPhaseTime(-10.0f)
  207.         , m_lastAmbientFireUpdateTime(-10.0f)
  208.         , m_lastExpensiveAccessoryUpdateTime(-10.0f)
  209.         , m_lastGroupUpdateTime(-10.0f)
  210.         , m_nFrameTicks(0)
  211.         , m_agentDebugTarget(0)
  212. {
  213.         ZeroArray(m_AlertnessCounters);
  214.         ZeroArray(m_pAreaList);
  215.  
  216.         //TODO see if we can init the actual environment yet?
  217.         gAIEnv.CVars.Init(); // CVars need to be init before any logging takes place
  218.         gAIEnv.SignalCRCs.Init();
  219.  
  220.         REGISTER_COMMAND("ai_reload", (ConsoleCommandFunc)ReloadConsoleCommand, VF_CHEAT, "Reload AI system scripts and data");
  221.         REGISTER_COMMAND("ai_CheckGoalpipes", (ConsoleCommandFunc)CheckGoalpipes, VF_CHEAT, "Checks goalpipes and dumps report to console.");
  222.         REGISTER_COMMAND("ai_dumpCheckpoints", (ConsoleCommandFunc)DumpCodeCoverageCheckpoints, VF_CHEAT, "Dump CodeCoverage checkpoints to file");
  223.         REGISTER_COMMAND("ai_Recorder_Start", (ConsoleCommandFunc)StartAIRecorder, VF_CHEAT, "Reset and start the AI Recorder on demand");
  224.         REGISTER_COMMAND("ai_Recorder_Stop", (ConsoleCommandFunc)StopAIRecorder, VF_CHEAT, "Stop the AI Recorder. If logging in memory, saves it to disk.");
  225.  
  226.         CFlightNavRegion2::InitCVars();
  227.         CTacticalPointSystem::RegisterCVars();
  228.  
  229. #ifdef CRYAISYSTEM_DEBUG
  230.         m_Recorder.Init();
  231.         gAIEnv.SetAIRecorder(&m_Recorder);
  232. #endif //CRYAISYSTEM_DEBUG
  233.  
  234.         // Don't Init() here! It will be called later after creation of the Entity System
  235.         //      Init();
  236. }
  237. //
  238. //-----------------------------------------------------------------------------------------------------------
  239. CAISystem::~CAISystem()
  240. {
  241.         if (GetISystem() && GetISystem()->GetISystemEventDispatcher())
  242.                 GetISystem()->GetISystemEventDispatcher()->RemoveListener(this);
  243.  
  244.         //Reset(IAISystem::RESET_EXIT_GAME);
  245.  
  246.         m_PipeManager.ClearAllGoalPipes();
  247.  
  248.         // (MATT) Note that we need to later trigger the object tracker to release all the objects {2009/03/25}
  249.         if (gAIEnv.pAIObjectManager)
  250.                 gAIEnv.pAIObjectManager->Reset();
  251.  
  252.         m_mapFaction.clear();
  253.         m_mapGroups.clear();
  254.         m_mapBeacons.clear();
  255.  
  256.         for (AIGroupMap::iterator it = m_mapAIGroups.begin(); it != m_mapAIGroups.end(); ++it)
  257.                 delete it->second;
  258.         m_mapAIGroups.clear();
  259.  
  260.         if (m_pNavigation)
  261.                 m_pNavigation->ShutDown();
  262.  
  263.         if (gAIEnv.pTargetTrackManager)
  264.                 gAIEnv.pTargetTrackManager->Shutdown();
  265.  
  266.         delete m_pSmartObjectManager;
  267.         delete m_pAIActionManager;
  268.  
  269.         // Release fire command factory.
  270.         for (std::vector<IFireCommandDesc*>::iterator it = m_firecommandDescriptors.begin(); it != m_firecommandDescriptors.end(); ++it)
  271.                 (*it)->Release();
  272.         m_firecommandDescriptors.clear();
  273.  
  274.         SAFE_RELEASE(m_pScriptAI);
  275.  
  276.         // (MATT) Flush all the objects that have been deregistered.
  277.         // Really, this should delete all AI objects regardless {2009/03/27}
  278.         if (gAIEnv.pObjectContainer)
  279.         {
  280.                 gAIEnv.pObjectContainer->ReleaseDeregisteredObjects(true);
  281.                 gAIEnv.pObjectContainer->Reset();
  282.         }
  283.  
  284.         if (gAIEnv.pPathfinderNavigationSystemUser)
  285.         {
  286.                 gAIEnv.pNavigationSystem->UnRegisterUser(gAIEnv.pPathfinderNavigationSystemUser);
  287.                 delete gAIEnv.pPathfinderNavigationSystemUser;
  288.                 gAIEnv.pMNMPathfinder = 0;
  289.         }
  290.  
  291.         delete m_pNavigation;
  292.         gAIEnv.pNavigation = m_pNavigation = 0;
  293.  
  294.         delete m_pGraph;
  295.         gAIEnv.pGraph = m_pGraph = 0;
  296.  
  297.         SAFE_DELETE(gAIEnv.pPerceptionManager);
  298.         SAFE_DELETE(gAIEnv.pCommunicationManager);
  299.         SAFE_DELETE(gAIEnv.pCoverSystem);
  300.         SAFE_DELETE(gAIEnv.pNavigationSystem);
  301.         SAFE_DELETE(gAIEnv.pSelectionTreeManager);
  302.         SAFE_DELETE(gAIEnv.pBehaviorTreeManager);
  303.         SAFE_DELETE(gAIEnv.pGraftManager);
  304.         SAFE_DELETE(gAIEnv.pVisionMap);
  305.         SAFE_DELETE(gAIEnv.pFactionMap);
  306.         SAFE_DELETE(gAIEnv.pGroupManager);
  307.         SAFE_DELETE(gAIEnv.pRayCaster);
  308.         SAFE_DELETE(gAIEnv.pIntersectionTester);
  309.         SAFE_DELETE(gAIEnv.pMovementSystem);
  310.         SAFE_DELETE(gAIEnv.pSequenceManager);
  311.         SAFE_DELETE(gAIEnv.pClusterDetector);
  312.  
  313. #ifdef CRYAISYSTEM_DEBUG
  314.         SAFE_DELETE(gAIEnv.pBubblesSystem);
  315. #endif
  316.  
  317.         gAIEnv.ShutDown();
  318. }
  319.  
  320. //-----------------------------------------------------------------------------------------------------------
  321.  
  322. bool CAISystem::Init()
  323. {
  324.         LOADING_TIME_PROFILE_SECTION;
  325.  
  326.         AILogProgress("[AISYSTEM] Initialization started.");
  327.  
  328.         GetISystem()->GetISystemEventDispatcher()->RegisterListener(this);
  329.  
  330.         SetupAIEnvironment();
  331.  
  332.         // ensure the available communications are ready before the AI scripts get loaded (they in turn might load GoalPipes and other stuff that depend on communication data)
  333.         gAIEnv.pCommunicationManager->LoadConfigurationAndScanRootFolder("Scripts/AI/Communication");
  334.  
  335.         if (!m_pScriptAI)
  336.                 m_pScriptAI = new CScriptBind_AI();
  337.  
  338.         Reset(IAISystem::RESET_INTERNAL);
  339.  
  340.         m_nTickCount = 0;
  341.         gAIEnv.pWorld = gEnv->pPhysicalWorld;
  342.  
  343.         m_frameStartTime = gEnv->pTimer->GetFrameStartTime();
  344.         m_fLastPuppetUpdateTime = m_frameStartTime;
  345.         m_frameDeltaTime = 0.0f;
  346.         m_frameStartTimeSeconds = m_frameStartTime.GetSeconds();
  347.  
  348.         // Register fire command factories.
  349.         RegisterFirecommandHandler(CREATE_FIRECOMMAND_DESC("instant", CFireCommandInstant));
  350.         RegisterFirecommandHandler(CREATE_FIRECOMMAND_DESC("instant_single", CFireCommandInstantSingle));
  351.         RegisterFirecommandHandler(CREATE_FIRECOMMAND_DESC("projectile_slow", CFireCommandProjectileSlow));
  352.         RegisterFirecommandHandler(CREATE_FIRECOMMAND_DESC("projectile_fast", CFireCommandProjectileFast));
  353.         RegisterFirecommandHandler(CREATE_FIRECOMMAND_DESC("grenade", CFireCommandGrenade));
  354. #if 0
  355.         // deprecated and won't compile at all...
  356.         RegisterFirecommandHandler(CREATE_FIRECOMMAND_DESC("strafing", CFireCommandStrafing));
  357.         RegisterFirecommandHandler(CREATE_FIRECOMMAND_DESC("hurricane", CFireCommandHurricane));
  358.         // TODO: move this to game.dll
  359.         RegisterFirecommandHandler(CREATE_FIRECOMMAND_DESC("fast_light_moar", CFireCommandFastLightMOAR));
  360.         RegisterFirecommandHandler(CREATE_FIRECOMMAND_DESC("hunter_moar", CFireCommandHunterMOAR));
  361.         RegisterFirecommandHandler(CREATE_FIRECOMMAND_DESC("hunter_sweep_moar", CFireCommandHunterSweepMOAR));
  362.         RegisterFirecommandHandler(CREATE_FIRECOMMAND_DESC("hunter_singularity_cannon", CFireCommandHunterSingularityCannon));
  363. #endif
  364.         m_bInitialized = true;
  365.  
  366.         if (gAIEnv.pTargetTrackManager)
  367.                 gAIEnv.pTargetTrackManager->Init();
  368.  
  369.         gAIEnv.pSelectionTreeManager->ScanFolder("Scripts/AI/SelectionTrees");
  370.  
  371.         BehaviorTree::RegisterBehaviorTreeNodes();
  372.  
  373.         AILogProgress("[AISYSTEM] Initialization finished.");
  374.  
  375.         if (gEnv->IsEditor())
  376.         {
  377.                 if (!gAIEnv.pGraph)
  378.                 {
  379.                         gAIEnv.pGraph = m_pGraph = new CGraph;
  380.                 }
  381.                 if (!gAIEnv.pNavigation)
  382.                 {
  383.                         gAIEnv.pNavigation = m_pNavigation = new CNavigation(gEnv->pSystem);
  384.                         m_pNavigation->Init();
  385.                 }
  386.                 if (!gAIEnv.pCoverSystem)
  387.                 {
  388.                         gAIEnv.pCoverSystem = new CCoverSystem("Scripts/AI/Cover.xml");
  389.                 }
  390.                 if (!gAIEnv.pNavigationSystem)
  391.                 {
  392.                         gAIEnv.pNavigationSystem = new NavigationSystem("Scripts/AI/Navigation.xml");
  393.                 }
  394.                 if (!gAIEnv.pMNMPathfinder)
  395.                 {
  396.                         gAIEnv.pPathfinderNavigationSystemUser = new MNM::PathfinderNavigationSystemUser;
  397.                         gAIEnv.pMNMPathfinder = gAIEnv.pPathfinderNavigationSystemUser->GetPathfinderImplementation();
  398.                         assert(gAIEnv.pNavigationSystem);
  399.                         gAIEnv.pNavigationSystem->RegisterUser(gAIEnv.pPathfinderNavigationSystemUser, "PathfinderExtension");
  400.                 }
  401.                 if (!gAIEnv.pVisionMap)
  402.                 {
  403.                         gAIEnv.pVisionMap = new CVisionMap();
  404.                 }
  405.                 if (!gAIEnv.pGroupManager)
  406.                 {
  407.                         gAIEnv.pGroupManager = new CGroupManager();
  408.                 }
  409.                 if (!gAIEnv.pAIActionManager)
  410.                 {
  411.                         gAIEnv.pAIActionManager = m_pAIActionManager = new CAIActionManager();
  412.                 }
  413.                 if (!gAIEnv.pSmartObjectManager)
  414.                 {
  415.                         gAIEnv.pSmartObjectManager = m_pSmartObjectManager = new CSmartObjectManager();
  416.                 }
  417.                 if (!gAIEnv.pRayCaster)
  418.                 {
  419.                         gAIEnv.pRayCaster = new SAIEnvironment::GlobalRayCaster;
  420.                         gAIEnv.pRayCaster->SetQuota(gAIEnv.CVars.RayCasterQuota);
  421.                 }
  422.                 if (!gAIEnv.pIntersectionTester)
  423.                 {
  424.                         gAIEnv.pIntersectionTester = new SAIEnvironment::GlobalIntersectionTester;
  425.                         gAIEnv.pIntersectionTester->SetQuota(gAIEnv.CVars.IntersectionTesterQuota);
  426.                 }
  427.                 if (!gAIEnv.pMovementSystem)
  428.                 {
  429.                         gAIEnv.pMovementSystem = MovementSystemCreator().CreateMovementSystem();
  430.                 }
  431.                 if (!gAIEnv.pSequenceManager)
  432.                 {
  433.                         gAIEnv.pSequenceManager = new AIActionSequence::SequenceManager();
  434.                 }
  435.                 if (!gAIEnv.pClusterDetector)
  436.                 {
  437.                         gAIEnv.pClusterDetector = new ClusterDetector();
  438.                 }
  439.                 if (!gAIEnv.pActorLookUp)
  440.                 {
  441.                         gAIEnv.pActorLookUp = new ActorLookUp();
  442.                 }
  443.                 if (!gAIEnv.pFactionMap)
  444.                 {
  445.                         gAIEnv.pFactionMap = new CFactionMap();
  446.                 }
  447.                 if (!gAIEnv.pWalkabilityCacheManager)
  448.                 {
  449.                         gAIEnv.pWalkabilityCacheManager = new WalkabilityCacheManager();
  450.                 }
  451.                 if (!gAIEnv.pTacticalPointSystem)
  452.                 {
  453.                         gAIEnv.pTacticalPointSystem = new CTacticalPointSystem();
  454.                         g_flyHelpersTacticalLanguageExtender.Initialize();
  455.                 }
  456.         }
  457.  
  458.         m_AIObjectManager.Init();
  459.         m_globalPerceptionScale.Reload();
  460.  
  461.         return true;
  462. }
  463.  
  464. bool CAISystem::CompleteInit()
  465. {
  466. #ifndef _LIB
  467.         AIFlowBaseNode::RegisterFlowNodes();
  468. #endif
  469.  
  470.         return true;
  471. }
  472.  
  473. void CAISystem::SetAIHacksConfiguration()
  474. {
  475.         /////////////////////////////////////////////////////////////
  476.         //TODO This is hack support and should go away at some point!
  477.         // Set the compatibility mode for feature/setting emulation
  478.         const char* sValue = gAIEnv.CVars.CompatibilityMode;
  479.  
  480.         EConfigCompatabilityMode eCompatMode = ECCM_CRYSIS2;
  481.  
  482.         if (strcmpi("crysis", sValue) == 0)
  483.                 eCompatMode = ECCM_CRYSIS;
  484.         if (strcmpi("game04", sValue) == 0)
  485.                 eCompatMode = ECCM_GAME04;
  486.         if (strcmpi("warface", sValue) == 0)
  487.                 eCompatMode = ECCM_WARFACE;
  488.         if (strcmpi("crysis2", sValue) == 0)
  489.                 eCompatMode = ECCM_CRYSIS2;
  490.         gAIEnv.configuration.eCompatibilityMode = eCompatMode;
  491.         /////////////////////////////////////////////////////////////
  492. }
  493.  
  494. void CAISystem::SetupAIEnvironment()
  495. {
  496.         SetAIHacksConfiguration();
  497.  
  498.         //TODO make these members of CAISystem that are pointed to, NOT allocated!
  499.  
  500.         if (!gAIEnv.pActorLookUp)
  501.                 gAIEnv.pActorLookUp = new ActorLookUp();
  502.  
  503.         if (!gAIEnv.pWalkabilityCacheManager)
  504.                 gAIEnv.pWalkabilityCacheManager = new WalkabilityCacheManager();
  505.  
  506.         gAIEnv.pAIObjectManager = &m_AIObjectManager;
  507.  
  508.         gAIEnv.pPipeManager = &m_PipeManager;
  509.  
  510.         // GoalOpFactory
  511.         if (!gAIEnv.pGoalOpFactory)
  512.         {
  513.                 CGoalOpFactoryOrdering* pFactoryOrdering = new CGoalOpFactoryOrdering();
  514.                 gAIEnv.pGoalOpFactory = pFactoryOrdering;
  515.  
  516.                 //TODO move these out of AISystem, to be added thru interface function from game side
  517.                 pFactoryOrdering->PrepareForFactories(3);
  518.                 pFactoryOrdering->AddFactory(new CGoalOpFactoryCrysis2);
  519.  
  520. #if 0
  521.                 // deprecated and won't compile at all...
  522.                 pFactoryOrdering->AddFactory(new CGoalOpFactoryG04);
  523. #endif
  524.  
  525.                 pFactoryOrdering->AddFactory(new CGoalOpFactoryG02);
  526.         }
  527.  
  528.         // ObjectContainer
  529.         if (!gAIEnv.pObjectContainer)
  530.                 gAIEnv.pObjectContainer = new CObjectContainer;
  531.  
  532. #if !defined(_RELEASE)
  533.         // CodeCoverage
  534.         if (!gAIEnv.pCodeCoverageTracker)
  535.                 gAIEnv.pCodeCoverageTracker = new CCodeCoverageTracker;
  536.         if (!gAIEnv.pCodeCoverageManager)
  537.                 gAIEnv.pCodeCoverageManager = new CCodeCoverageManager;
  538.         if (!gAIEnv.pCodeCoverageGUI)
  539.                 gAIEnv.pCodeCoverageGUI = new CCodeCoverageGUI;
  540. #endif
  541.  
  542.         // StatsManager
  543.         if (!gAIEnv.pStatsManager)
  544.                 gAIEnv.pStatsManager = new CStatsManager;
  545.  
  546.         if (!gAIEnv.pTargetTrackManager)
  547.                 gAIEnv.pTargetTrackManager = new CTargetTrackManager();
  548.  
  549.         gAIEnv.pAIActionManager = m_pAIActionManager = new CAIActionManager();
  550.         gAIEnv.pSmartObjectManager = m_pSmartObjectManager = new CSmartObjectManager();
  551.  
  552.         gAIEnv.pPerceptionManager = new CPerceptionManager();
  553.         gAIEnv.pCommunicationManager = new CCommunicationManager("Scripts/AI/Communication/CommunicationSystemConfiguration.xml");
  554.         gAIEnv.pSelectionTreeManager = new CSelectionTreeManager();
  555.         gAIEnv.pBehaviorTreeManager = new BehaviorTree::BehaviorTreeManager();
  556.         gAIEnv.pGraftManager = new BehaviorTree::GraftManager();
  557.  
  558.         if (!gAIEnv.pFactionMap)
  559.         {
  560.                 gAIEnv.pFactionMap = new CFactionMap();
  561.                 m_globalPerceptionScale.Reload();
  562.         }
  563.  
  564.         gAIEnv.pCollisionAvoidanceSystem = new CollisionAvoidanceSystem();
  565.  
  566.         gAIEnv.pRayCaster = new SAIEnvironment::GlobalRayCaster;
  567.         gAIEnv.pRayCaster->SetQuota(gAIEnv.CVars.RayCasterQuota);
  568.  
  569.         gAIEnv.pIntersectionTester = new SAIEnvironment::GlobalIntersectionTester;
  570.         gAIEnv.pIntersectionTester->SetQuota(gAIEnv.CVars.IntersectionTesterQuota);
  571.  
  572.         gAIEnv.pMovementSystem = MovementSystemCreator().CreateMovementSystem();
  573.  
  574.         gAIEnv.pSequenceManager = new AIActionSequence::SequenceManager();
  575.  
  576.         gAIEnv.pClusterDetector = new ClusterDetector();
  577.  
  578. #ifdef CRYAISYSTEM_DEBUG
  579.         if (!gAIEnv.pBubblesSystem)
  580.         {
  581.                 gAIEnv.pBubblesSystem = new CAIBubblesSystem();
  582.                 gAIEnv.pBubblesSystem->Init();
  583.         }
  584. #endif // CRYAISYSTEM_DEBUG
  585. }
  586.  
  587. //
  588. //-----------------------------------------------------------------------------------------------------------
  589. bool CAISystem::InitSmartObjects()
  590. {
  591.         AILogProgress("[AISYSTEM] Initializing AI Actions.");
  592.         m_pAIActionManager->LoadLibrary(AI_ACTIONS_PATH);
  593.  
  594.         AILogProgress("[AISYSTEM] Initializing Smart Objects.");
  595.         m_pSmartObjectManager->LoadSmartObjectsLibrary();
  596.  
  597.         return true;
  598. }
  599.  
  600. //====================================================================
  601. // Reload
  602. //====================================================================
  603. void CAISystem::Reload()
  604. {
  605.         gEnv->pLog->Log("-------------------------------------------");
  606.         gEnv->pLog->Log("Reloading AI...");
  607.  
  608.         // Clear out any state that would otherwise persist over a reload (e.g. goalpipes)
  609.         ClearForReload();
  610.  
  611.         gAIEnv.pCommunicationManager->Reload();
  612.         gAIEnv.pSelectionTreeManager->Reload();
  613.  
  614.         gAIEnv.pFactionMap->Reload();
  615.         m_globalPerceptionScale.Reload();
  616.         g_flyHelpersTacticalLanguageExtender.Initialize();
  617.  
  618.         // Reload the root of the AI system scripts, forcing reload of this and all dependencies
  619.         IScriptSystem* pSS = gEnv->pScriptSystem;
  620.         CRY_ASSERT(pSS);
  621.         if (pSS->ExecuteFile("Scripts/AI/aiconfig.lua", true, true))
  622.         {
  623.                 // Reset blackboards etc.
  624.                 pSS->BeginCall("AIReset");
  625.                 pSS->EndCall();
  626.  
  627.                 // Reload goal pipes, queries etc.
  628.                 pSS->BeginCall("AIReload");
  629.                 pSS->EndCall();
  630.         }
  631.  
  632.         if (gAIEnv.pTargetTrackManager)
  633.                 gAIEnv.pTargetTrackManager->ReloadConfig();
  634.  
  635.         gAIEnv.pCoverSystem->ReloadConfig();
  636.  
  637.         gAIEnv.pBehaviorTreeManager->Reset();
  638.         gAIEnv.pGraftManager->Reset();
  639. }
  640.  
  641. //====================================================================
  642. // SetLevelPath
  643. //====================================================================
  644. void CAISystem::SetLevelPath(const char* sPath)
  645. {
  646.         m_sWorkingFolder = sPath;
  647. }
  648.  
  649. //====================================================================
  650. // RegisterListener
  651. //====================================================================
  652. bool CAISystem::RegisterListener(IAISystemListener* pListener)
  653. {
  654.         bool result;
  655.         result = m_setSystemListeners.insert(pListener).second;
  656.         return result;
  657. }
  658.  
  659. //====================================================================
  660. // UnregisterListener
  661. //====================================================================
  662. bool CAISystem::UnregisterListener(IAISystemListener* pListener)
  663. {
  664.         int nErased;
  665.         nErased = m_setSystemListeners.erase(pListener);
  666.         if (m_setSystemListeners.empty())
  667.                 stl::free_container(m_setSystemListeners);
  668.         return (nErased == 1);
  669. }
  670.  
  671. //====================================================================
  672. // OnAgentDeath
  673. //====================================================================
  674. void CAISystem::OnAgentDeath(EntityId deadEntityID, EntityId killerID)
  675. {
  676.         BroadcastToListeners(OnAgentDeath(deadEntityID, killerID));
  677. }
  678.  
  679. //====================================================================
  680. // InvalidatePathsThroughArea
  681. //====================================================================
  682. void CAISystem::InvalidatePathsThroughArea(const ListPositions& areaShape)
  683. {
  684.         for (AIObjectOwners::iterator it = gAIEnv.pAIObjectManager->m_Objects.begin(); it != gAIEnv.pAIObjectManager->m_Objects.end(); ++it)
  685.         {
  686.                 CAIObject* pObject = it->second.GetAIObject();
  687.                 CPipeUser* pPiper = pObject->CastToCPipeUser();
  688.                 if (pPiper)
  689.                 {
  690.                         const CNavPath& path = pPiper->m_Path;
  691.                         const TPathPoints& listPath = path.GetPath();
  692.                         Vec3 pos = pPiper->GetPhysicsPos();
  693.                         for (TPathPoints::const_iterator pathIt = listPath.begin(); pathIt != listPath.end(); ++pathIt)
  694.                         {
  695.                                 Lineseg pathSeg(pos, pathIt->vPos);
  696.                                 pos = pathIt->vPos;
  697.                                 if (Overlap::Lineseg_Polygon2D(pathSeg, areaShape))
  698.                                 {
  699.                                         pPiper->PathIsInvalid();
  700.                                         break;
  701.                                 }
  702.                         }
  703.                 }
  704.         } // loop over objects
  705. }
  706.  
  707. //
  708. //-----------------------------------------------------------------------------------------------------------
  709. int CAISystem::GetAlertness() const
  710. {
  711.         int maxAlertness = 0;
  712.         for (int i = NUM_ALERTNESS_COUNTERS - 1; i; i--)
  713.                 if (m_AlertnessCounters[i])
  714.                 {
  715.                         maxAlertness = i;
  716.                         break;
  717.                 }
  718.         return maxAlertness;
  719. }
  720.  
  721. //
  722. //-----------------------------------------------------------------------------------------------------------
  723. int CAISystem::GetAlertness(const IAIAlertnessPredicate& alertnessPredicate)
  724. {
  725.         int maxAlertness = 0;
  726.  
  727.         ActorLookUp& lookUp = *gAIEnv.pActorLookUp;
  728.         lookUp.Prepare(ActorLookUp::Proxy);
  729.  
  730.         size_t activeActorCount = lookUp.GetActiveCount();
  731.  
  732.         for (size_t actorIndex = 0; actorIndex < activeActorCount; ++actorIndex)
  733.         {
  734.                 CAIActor* pAIActor = lookUp.GetActor<CAIActor>(actorIndex);
  735.                 IAIActorProxy* pProxy = lookUp.GetProxy(actorIndex);
  736.  
  737.                 if ((pProxy != NULL) && alertnessPredicate.ConsiderAIObject(pAIActor))
  738.                 {
  739.                         maxAlertness = max(maxAlertness, pProxy->GetAlertnessState());
  740.                 }
  741.         }
  742.  
  743.         return maxAlertness;
  744. }
  745.  
  746. //
  747. //-----------------------------------------------------------------------------------------------------------
  748. void CAISystem::ClearForReload(void)
  749. {
  750.         m_PipeManager.ClearAllGoalPipes();
  751.         g_flyHelpersTacticalLanguageExtender.Deinitialize();
  752.         gAIEnv.pTacticalPointSystem->DestroyAllQueries();
  753. }
  754.  
  755. //
  756. //-----------------------------------------------------------------------------------------------------------
  757. void CAISystem::ReloadConsoleCommand(IConsoleCmdArgs* pArgs)
  758. {
  759.         // Needs to be static function to be registered as console command
  760.         // The arguments are not used
  761.         GetAISystem()->Reload();
  762. }
  763.  
  764. //
  765. //-----------------------------------------------------------------------------------------------------------
  766. void CAISystem::StartAIRecorder(IConsoleCmdArgs* pArgs)
  767. {
  768. #ifdef CRYAISYSTEM_DEBUG
  769.  
  770.         if (pArgs->GetArgCount() < 2)
  771.         {
  772.                 gEnv->pAISystem->Warning("<StartAIRecorder> ", "Expecting record mode as argument (1 == Memory, 2 == Disk)");
  773.                 return;
  774.         }
  775.  
  776.         char const* szMode = pArgs->GetArg(1);
  777.         char const* szFile = pArgs->GetArgCount() > 2 ? pArgs->GetArg(2) : NULL;
  778.  
  779.         EAIRecorderMode mode = eAIRM_Off;
  780.         if (strcmp(szMode, "1") == 0)
  781.                 mode = eAIRM_Memory;
  782.         else if (strcmp(szMode, "2") == 0)
  783.                 mode = eAIRM_Disk;
  784.  
  785.         string sRealFile;
  786.         if (szFile)
  787.                 sRealFile = PathUtil::Make("", szFile, "rcd");
  788.  
  789.         if (mode > eAIRM_Off)
  790.         {
  791.                 CAISystem* pAISystem = GetAISystem();
  792.                 pAISystem->m_Recorder.Reset();
  793.                 pAISystem->m_Recorder.Start(mode, sRealFile.c_str());
  794.         }
  795.  
  796. #endif //CRYAISYSTEM_DEBUG
  797. }
  798.  
  799. //
  800. //-----------------------------------------------------------------------------------------------------------
  801. void CAISystem::StopAIRecorder(IConsoleCmdArgs* pArgs)
  802. {
  803. #ifdef CRYAISYSTEM_DEBUG
  804.  
  805.         char const* szFile = pArgs->GetArgCount() > 1 ? pArgs->GetArg(1) : NULL;
  806.  
  807.         string sRealFile;
  808.         if (szFile)
  809.                 sRealFile = PathUtil::Make("", szFile, "rcd");
  810.  
  811.         GetAISystem()->m_Recorder.Stop(sRealFile.c_str());
  812.  
  813. #endif //CRYAISYSTEM_DEBUG
  814. }
  815.  
  816. //====================================================================
  817. // CheckUnusedGoalpipes
  818. //====================================================================
  819. void CAISystem::CheckGoalpipes(IConsoleCmdArgs*)
  820. {
  821.         GetAISystem()->m_PipeManager.CheckGoalpipes();
  822. }
  823.  
  824. void CAISystem::DumpCodeCoverageCheckpoints(IConsoleCmdArgs* pArgs)
  825. {
  826. #if !defined(_RELEASE)
  827.         if (gAIEnv.pCodeCoverageManager)
  828.         {
  829.                 // Any second argument triggers dump to file rather than log
  830.                 bool bLogToFile = (pArgs->GetArgCount() > 1);
  831.                 gAIEnv.pCodeCoverageManager->DumpCheckpoints(bLogToFile);
  832.         }
  833. #endif
  834. }
  835.  
  836. //
  837. //-----------------------------------------------------------------------------------------------------------
  838. CAIObject* CAISystem::GetPlayer() const
  839. {
  840.         AIObjectOwners::const_iterator ai;
  841.         if ((ai = gAIEnv.pAIObjectManager->m_Objects.find(AIOBJECT_PLAYER)) != gAIEnv.pAIObjectManager->m_Objects.end())
  842.                 return ai->second.GetAIObject();
  843.         return 0;
  844. }
  845.  
  846. // Sends a signal using the desired filter to the desired agents
  847. //
  848. //-----------------------------------------------------------------------------------------------------------
  849. void CAISystem::SendSignal(unsigned char cFilter, int nSignalId, const char* szText, IAIObject* pSenderObject, IAISignalExtraData* pData, uint32 crcCode /*= 0*/)
  850. {
  851.         // (MATT) This is quite a switch statement. Needs replacing. {2009/02/11}
  852.         CCCPOINT(CAISystem_SendSignal);
  853.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_AI);
  854.  
  855.         // This deletes the passed pData parameter if it wasn't set to NULL
  856.         struct DeleteBeforeReturning
  857.         {
  858.                 IAISignalExtraData** _p;
  859.                 DeleteBeforeReturning(IAISignalExtraData** p) : _p(p) {}
  860.                 ~DeleteBeforeReturning()
  861.                 {
  862.                         if (*_p)
  863.                                 delete (AISignalExtraData*)*_p;
  864.                 }
  865.         } autoDelete(&pData);
  866.  
  867.         // Calling this with no senderObject is an error
  868.         assert(pSenderObject);
  869.  
  870.         CAIActor* pSender = CastToCAIActorSafe(pSenderObject);
  871.         //filippo: can be that sender is null, for example when you send this signal in multiplayer.
  872.         if (!pSender)
  873.                 return;
  874.  
  875.         float fRange = pSender->GetParameters().m_fCommRange;
  876.         fRange *= pSender->GetParameters().m_fCommRange;
  877.         Vec3 pos = pSender->GetPos();
  878.         IEntity* pSenderEntity(pSender->GetEntity());
  879.  
  880.         CWeakRef<CAIObject> refSender = GetWeakRefSafe(pSender);
  881.  
  882.         switch (cFilter)
  883.         {
  884.  
  885.         case SIGNALFILTER_SENDER:
  886.                 {
  887.                         pSender->SetSignal(nSignalId, szText, pSenderEntity, pData, crcCode);
  888.                         pData = NULL;
  889.                         break;
  890.                 }
  891.         case SIGNALFILTER_HALFOFGROUP:
  892.                 {
  893.                         CCCPOINT(CAISystem_SendSignal_HALFOFGROUP);
  894.  
  895.                         int groupid = pSender->GetGroupId();
  896.                         AIObjects::iterator ai;
  897.  
  898.                         if ((ai = m_mapGroups.find(groupid)) != m_mapGroups.end())
  899.                         {
  900.                                 int groupmembers = m_mapGroups.count(groupid);
  901.                                 groupmembers /= 2;
  902.  
  903.                                 for (; ai != m_mapGroups.end(); )
  904.                                 {
  905.                                         if ((ai->first != groupid) || (!groupmembers--))
  906.                                                 break;
  907.  
  908.                                         // Object may have been removed
  909.                                         CAIActor* pReciever = CastToCAIActorSafe(ai->second.GetAIObject());
  910.                                         if ((pReciever != NULL) && pReciever != pSenderObject)
  911.                                         {
  912.                                                 pReciever->SetSignal(nSignalId, szText, pSenderEntity, pData ? new AISignalExtraData(*(AISignalExtraData*)pData) : NULL, crcCode);
  913.                                         }
  914.                                         else
  915.                                                 ++groupmembers;   // dont take into account sender
  916.                                         ++ai;
  917.                                 }
  918.                                 // don't delete pData!!! - it will be deleted at the end of this function
  919.                         }
  920.                 }
  921.                 break;
  922.         case SIGNALFILTER_NEARESTGROUP:
  923.                 {
  924.                         int groupid = pSender->GetGroupId();
  925.                         AIObjects::iterator ai;
  926.                         CAIActor* pNearest = 0;
  927.                         float mindist = 2000;
  928.                         if ((ai = m_mapGroups.find(groupid)) != m_mapGroups.end())
  929.                         {
  930.                                 for (; ai != m_mapGroups.end(); ++ai)
  931.                                 {
  932.                                         if (ai->first != groupid)
  933.                                                 break;
  934.  
  935.                                         CAIObject* pObject = ai->second.GetAIObject();
  936.  
  937.                                         if ((pObject != NULL) && (pObject != pSenderObject))
  938.                                         {
  939.                                                 float dist = (pObject->GetPos() - pSender->GetPos()).GetLength();
  940.                                                 if (dist < mindist)
  941.                                                 {
  942.                                                         pNearest = pObject->CastToCAIActor();
  943.                                                         if (pNearest)
  944.                                                                 mindist = (pObject->GetPos() - pSender->GetPos()).GetLength();
  945.                                                 }
  946.                                         }
  947.                                 }
  948.  
  949.                                 if (pNearest)
  950.                                 {
  951.                                         pNearest->SetSignal(nSignalId, szText, pSenderEntity, pData, crcCode);
  952.                                         pData = NULL;
  953.                                 }
  954.                         }
  955.                 }
  956.                 break;
  957.  
  958.         case SIGNALFILTER_NEARESTINCOMM:
  959.                 {
  960.                         int groupid = pSender->GetGroupId();
  961.                         AIObjects::iterator ai;
  962.                         CAIActor* pNearest = 0;
  963.                         float mindistSq = sqr(pSender->GetParameters().m_fCommRange);
  964.                         if ((ai = m_mapGroups.find(groupid)) != m_mapGroups.end())
  965.                         {
  966.                                 for (; ai != m_mapGroups.end(); ++ai)
  967.                                 {
  968.                                         if (ai->first == groupid)
  969.                                         {
  970.                                                 CAIObject* pObject = ai->second.GetAIObject();
  971.  
  972.                                                 if ((pObject != NULL) && (pObject != pSenderObject))
  973.                                                 {
  974.                                                         float distSq = (pObject->GetPos() - pSender->GetPos()).GetLengthSquared();
  975.                                                         if (distSq < mindistSq)
  976.                                                         {
  977.                                                                 if (pNearest = pObject->CastToCAIActor())
  978.                                                                         mindistSq = distSq;
  979.                                                         }
  980.                                                 }
  981.                                         }
  982.                                         else
  983.                                         {
  984.                                                 break;
  985.                                         }
  986.                                 }
  987.  
  988.                                 if (pNearest)
  989.                                 {
  990.                                         pNearest->SetSignal(nSignalId, szText, pSenderEntity, pData, crcCode);
  991.                                         pData = NULL;
  992.                                 }
  993.                         }
  994.                 }
  995.                 break;
  996.         case SIGNALFILTER_NEARESTINCOMM_LOOKING:
  997.                 {
  998.                         int groupid = pSender->GetGroupId();
  999.                         AIObjects::iterator ai;
  1000.                         CAIActor* pSenderActor = pSenderObject->CastToCAIActor();
  1001.                         CAIActor* pNearest = 0;
  1002.                         float mindist = pSender->GetParameters().m_fCommRange;
  1003.                         float closestDist2(std::numeric_limits<float>::max());
  1004.                         if (pSenderActor && (ai = m_mapGroups.find(groupid)) != m_mapGroups.end())
  1005.                         {
  1006.                                 for (; ai != m_mapGroups.end(); )
  1007.                                 {
  1008.                                         if (ai->first != groupid)
  1009.                                                 break;
  1010.  
  1011.                                         CAIObject* pObject = ai->second.GetAIObject();
  1012.  
  1013.                                         if ((pObject != NULL) && (pObject != pSenderObject))
  1014.                                         {
  1015.                                                 CPuppet* pCandidatePuppet = pObject->CastToCPuppet();
  1016.                                                 float dist = (pObject->GetPos() - pSender->GetPos()).GetLength();
  1017.                                                 if (pCandidatePuppet && dist < mindist)
  1018.                                                         if (CheckVisibilityToBody(pCandidatePuppet, pSenderActor, closestDist2))
  1019.                                                                 pNearest = pCandidatePuppet;
  1020.                                         }
  1021.                                         ++ai;
  1022.                                 }
  1023.                                 if (pNearest)
  1024.                                 {
  1025.                                         pNearest->SetSignal(nSignalId, szText, pSenderEntity, pData, crcCode);
  1026.                                         pData = NULL;
  1027.                                 }
  1028.                         }
  1029.                 }
  1030.                 break;
  1031.         case SIGNALFILTER_NEARESTINCOMM_FACTION:
  1032.                 {
  1033.                         uint8 factionID = pSender->GetFactionID();
  1034.                         AIObjects::iterator ai;
  1035.                         CAIActor* pNearest = 0;
  1036.                         float mindist = pSender->GetParameters().m_fCommRange;
  1037.                         if ((ai = m_mapFaction.find(factionID)) != m_mapFaction.end())
  1038.                         {
  1039.                                 for (; ai != m_mapFaction.end(); )
  1040.                                 {
  1041.                                         CAIObject* pObject = ai->second.GetAIObject();
  1042.                                         if (ai->first != factionID)
  1043.                                                 break;
  1044.  
  1045.                                         if (pObject && (pObject != pSenderObject && pObject->IsEnabled()))
  1046.                                         {
  1047.                                                 float dist = (pObject->GetPos() - pSender->GetPos()).GetLength();
  1048.                                                 if (dist < mindist)
  1049.                                                 {
  1050.                                                         pNearest = pObject->CastToCAIActor();
  1051.                                                         if (pNearest)
  1052.                                                                 mindist = (pObject->GetPos() - pSender->GetPos()).GetLength();
  1053.                                                 }
  1054.                                         }
  1055.                                         ++ai;
  1056.                                 }
  1057.  
  1058.                                 if (pNearest)
  1059.                                 {
  1060.                                         pNearest->SetSignal(nSignalId, szText, pSenderEntity, pData, crcCode);
  1061.                                         pData = NULL;
  1062.                                 }
  1063.                         }
  1064.                 }
  1065.                 break;
  1066.         case SIGNALFILTER_SUPERGROUP:
  1067.                 {
  1068.                         int groupid = pSender->GetGroupId();
  1069.                         AIObjects::iterator ai;
  1070.                         if ((ai = m_mapGroups.find(groupid)) != m_mapGroups.end())
  1071.                         {
  1072.                                 for (; ai != m_mapGroups.end(); ++ai)
  1073.                                 {
  1074.                                         CAIActor* pReciever = CastToCAIActorSafe(ai->second.GetAIObject());
  1075.                                         if (ai->first != groupid)
  1076.                                                 break;
  1077.                                         if (pReciever)
  1078.                                                 pReciever->SetSignal(nSignalId, szText, pSenderEntity, pData ? new AISignalExtraData(*(AISignalExtraData*)pData) : NULL, crcCode);
  1079.                                 }
  1080.                                 // don't delete pData!!! - it will be deleted at the end of this function
  1081.                         }
  1082.                         // send message also to player
  1083.                         CAIPlayer* pPlayer = CastToCAIPlayerSafe(GetPlayer());
  1084.                         if (pPlayer)
  1085.                         {
  1086. #pragma warning(push)
  1087. #pragma warning(disable:6011)
  1088.                                 if (pSender->GetParameters().m_nGroup == pPlayer->GetParameters().m_nGroup)
  1089.                                         pPlayer->SetSignal(nSignalId, szText, pSenderEntity, pData ? new AISignalExtraData(*(AISignalExtraData*)pData) : NULL, crcCode);
  1090. #pragma warning(pop)
  1091.                         }
  1092.                 }
  1093.                 break;
  1094.         case SIGNALFILTER_SUPERFACTION:
  1095.                 {
  1096.                         uint8 factionID = pSender->GetFactionID();
  1097.                         AIObjects::iterator ai;
  1098.  
  1099.                         if ((ai = m_mapFaction.find(factionID)) != m_mapFaction.end())
  1100.                         {
  1101.                                 for (; ai != m_mapFaction.end(); )
  1102.                                 {
  1103.                                         CAIActor* pReciever = CastToCAIActorSafe(ai->second.GetAIObject());
  1104.                                         if (ai->first != factionID)
  1105.                                                 break;
  1106.                                         if (pReciever)
  1107.                                                 pReciever->SetSignal(nSignalId, szText, pSenderEntity, pData ? new AISignalExtraData(*(AISignalExtraData*)pData) : NULL, crcCode);
  1108.                                         ++ai;
  1109.                                 }
  1110.                                 // don't delete pData!!! - it will be deleted at the end of this function
  1111.                         }
  1112.                         // send message also to player
  1113.                         CAIPlayer* pPlayer = CastToCAIPlayerSafe(GetPlayer());
  1114.                         if (pPlayer)
  1115.                         {
  1116.                                 pPlayer->SetSignal(nSignalId, szText, pSenderEntity, pData ? new AISignalExtraData(*(AISignalExtraData*)pData) : NULL, crcCode);
  1117.                         }
  1118.                 }
  1119.                 break;
  1120.  
  1121.         case SIGNALFILTER_GROUPONLY:
  1122.         case SIGNALFILTER_GROUPONLY_EXCEPT:
  1123.                 {
  1124.                         int groupid = pSender->GetGroupId();
  1125.  
  1126.                         // only send if non-zero group (there are similar checks in CAIActor::SetGroupId() and CGroupManager::NotifyGroup() to bypass this pseudo group)
  1127.                         if (groupid != 0)
  1128.                         {
  1129.  
  1130.                                 AIObjects::iterator ai;
  1131.                                 if ((ai = m_mapGroups.find(groupid)) != m_mapGroups.end())
  1132.                                 {
  1133.                                         for (; ai != m_mapGroups.end(); ++ai)
  1134.                                         {
  1135.                                                 CAIActor* pReciever = CastToCAIActorSafe(ai->second.GetAIObject());
  1136.                                                 if (ai->first != groupid)
  1137.                                                         break;
  1138.                                                 if ((pReciever != NULL) && !(cFilter == SIGNALFILTER_GROUPONLY_EXCEPT && pReciever == pSender))
  1139.                                                 {
  1140.                                                         pReciever->SetSignal(nSignalId, szText, pSenderEntity, pData ? new AISignalExtraData(*(AISignalExtraData*)pData) : NULL, crcCode);
  1141.                                                 }
  1142.                                         }
  1143.                                         // don't delete pData!!! - it will be deleted at the end of this function
  1144.                                 }
  1145.  
  1146.                                 // send message also to player
  1147.                                 CAIPlayer* pPlayer = CastToCAIPlayerSafe(GetPlayer());
  1148.                                 if (pPlayer)
  1149.                                 {
  1150.                                         if (pSender->GetParameters().m_nGroup == pPlayer->GetParameters().m_nGroup && Distance::Point_PointSq(pPlayer->GetPos(), pos) < fRange && !(cFilter == SIGNALFILTER_GROUPONLY_EXCEPT && pPlayer == pSender))
  1151.                                                 pPlayer->SetSignal(nSignalId, szText, pSenderEntity, pData ? new AISignalExtraData(*(AISignalExtraData*)pData) : NULL, crcCode);
  1152.                                 }
  1153.                         }
  1154.                 }
  1155.                 break;
  1156.         case SIGNALFILTER_FACTIONONLY:
  1157.                 {
  1158.                         uint8 factionID = pSender->GetFactionID();
  1159.                         AIObjects::iterator ai;
  1160.  
  1161.                         if ((ai = m_mapFaction.find(factionID)) != m_mapFaction.end())
  1162.                         {
  1163.                                 for (; ai != m_mapFaction.end(); ++ai)
  1164.                                 {
  1165.                                         CAIActor* pReciever = CastToCAIActorSafe(ai->second.GetAIObject());
  1166.                                         if (ai->first != factionID)
  1167.                                                 break;
  1168.                                         if (pReciever)
  1169.                                         {
  1170.                                                 Vec3 mypos = pReciever->GetPos();
  1171.                                                 mypos -= pos;
  1172.  
  1173.                                                 if (mypos.GetLengthSquared() < fRange)
  1174.                                                         pReciever->SetSignal(nSignalId, szText, pSenderEntity, pData ? new AISignalExtraData(*(AISignalExtraData*)pData) : NULL, crcCode);
  1175.                                         }
  1176.                                 }
  1177.                                 // don't delete pData!!! - it will be deleted at the end of this function
  1178.                         }
  1179.                         // send message also to player
  1180.                         CAIPlayer* pPlayer = CastToCAIPlayerSafe(GetPlayer());
  1181.                         if (pPlayer)
  1182.                         {
  1183.                                 if (pSender->GetFactionID() == pPlayer->GetFactionID() && Distance::Point_PointSq(pPlayer->GetPos(), pos) < fRange)
  1184.                                         pPlayer->SetSignal(nSignalId, szText, pSenderEntity, pData ? new AISignalExtraData(*(AISignalExtraData*)pData) : NULL, crcCode);
  1185.                         }
  1186.                 }
  1187.                 break;
  1188.         case SIGNALFILTER_ANYONEINCOMM:
  1189.         case SIGNALFILTER_ANYONEINCOMM_EXCEPT:
  1190.                 {
  1191.                         // send to puppets and aware objects in the communications range of the sender
  1192.  
  1193.                         // Added the evaluation of AIOBJECT_VEHICLE so that vehicles can get signals.
  1194.                         // 20/12/05 Tetsuji
  1195.                         AIObjectOwners::iterator ai;
  1196.  
  1197.                         std::vector<int> objectKinds;
  1198.                         objectKinds.push_back(AIOBJECT_ACTOR);
  1199.                         objectKinds.push_back(AIOBJECT_VEHICLE);
  1200.  
  1201.                         std::vector<int>::iterator ki, ki2, kiend = objectKinds.end();
  1202.  
  1203.                         for (ki = objectKinds.begin(); ki != kiend; ++ki)
  1204.                         {
  1205.                                 int objectKind = *ki;
  1206.                                 // first look for all the puppets
  1207.                                 if ((ai = gAIEnv.pAIObjectManager->m_Objects.find(objectKind)) != gAIEnv.pAIObjectManager->m_Objects.end())
  1208.                                 {
  1209.                                         for (; ai != gAIEnv.pAIObjectManager->m_Objects.end(); )
  1210.                                         {
  1211.                                                 for (ki2 = objectKinds.begin(); ki2 != kiend; ++ki2)
  1212.                                                         if (ai->first == *ki)
  1213.                                                         {
  1214.                                                                 CAIActor* pReciever = ai->second->CastToCAIActor();
  1215.                                                                 if (pReciever && Distance::Point_PointSq(pReciever->GetPos(), pos) < fRange && !(cFilter == SIGNALFILTER_ANYONEINCOMM_EXCEPT && pReciever == pSender))
  1216.                                                                         pReciever->SetSignal(nSignalId, szText, pSenderEntity, pData ? new AISignalExtraData(*(AISignalExtraData*)pData) : NULL, crcCode);
  1217.                                                         }
  1218.                                                 ++ai;
  1219.                                         }
  1220.                                 }
  1221.                                 // don't delete pData!!! - it will be deleted at the end of this function
  1222.                         }
  1223.  
  1224.                         // now look for aware objects
  1225.                         if ((ai = gAIEnv.pAIObjectManager->m_Objects.find(AIOBJECT_AWARE)) != gAIEnv.pAIObjectManager->m_Objects.end())
  1226.                         {
  1227.                                 for (; ai != gAIEnv.pAIObjectManager->m_Objects.end(); )
  1228.                                 {
  1229.                                         if (ai->first != AIOBJECT_AWARE)
  1230.                                                 break;
  1231.                                         CAIActor* pReciever = ai->second->CastToCAIActor();
  1232.                                         if (pReciever)
  1233.                                         {
  1234.                                                 Vec3 mypos = pReciever->GetPos();
  1235.                                                 mypos -= pos;
  1236.                                                 if (mypos.GetLengthSquared() < fRange)
  1237.                                                         pReciever->SetSignal(nSignalId, szText, pSenderEntity, pData ? new AISignalExtraData(*(AISignalExtraData*)pData) : NULL, crcCode);
  1238.                                         }
  1239.                                         ++ai;
  1240.                                 }
  1241.                         }
  1242.                         // send message also to player
  1243.  
  1244.                         CAIPlayer* pPlayer = CastToCAIPlayerSafe(GetPlayer());
  1245.                         if (pPlayer)
  1246.                         {
  1247.                                 if (Distance::Point_PointSq(pPlayer->GetPos(), pos) < fRange && !(cFilter == SIGNALFILTER_ANYONEINCOMM_EXCEPT && pPlayer == pSender))
  1248.                                 {
  1249.                                         PREFAST_SUPPRESS_WARNING(6011)
  1250.                                         pPlayer->SetSignal(nSignalId, szText, pSenderEntity, pData ? new AISignalExtraData(*(AISignalExtraData*)pData) : NULL, crcCode);
  1251.                                 }
  1252.                         }
  1253.                         // don't delete pData!!! - it will be deleted at the end of this function
  1254.                 }
  1255.                 break;
  1256.         case SIGNALFILTER_LEADER:
  1257.         case SIGNALFILTER_LEADERENTITY:
  1258.                 {
  1259.                         int groupid = pSender->GetGroupId();
  1260.                         AIObjects::iterator ai;
  1261.                         if ((ai = m_mapGroups.find(groupid)) != m_mapGroups.end())
  1262.                         {
  1263.                                 for (; ai != m_mapGroups.end(); )
  1264.                                 {
  1265.                                         CLeader* pLeader = CastToCLeaderSafe(ai->second.GetAIObject());
  1266.                                         if (ai->first != groupid)
  1267.                                                 break;
  1268.                                         if (pLeader)
  1269.                                         {
  1270.                                                 CAIObject* pRecipientObj = (cFilter == SIGNALFILTER_LEADER ? pLeader : pLeader->GetAssociation().GetAIObject());
  1271.                                                 if (pRecipientObj)
  1272.                                                 {
  1273.                                                         CAIActor* pRecipient = pRecipientObj->CastToCAIActor();
  1274.                                                         if (pRecipient)
  1275.                                                                 pRecipient->SetSignal(nSignalId, szText, pSenderEntity, pData ? new AISignalExtraData(*(AISignalExtraData*)pData) : NULL, crcCode);
  1276.                                                 }
  1277.                                                 break;
  1278.                                         }
  1279.                                         ++ai;
  1280.                                 }
  1281.                                 // don't delete pData!!! - it will be deleted at the end of this function
  1282.                         }
  1283.                 }
  1284.                 break;
  1285.  
  1286.         case SIGNALFILTER_FORMATION:
  1287.         case SIGNALFILTER_FORMATION_EXCEPT:
  1288.                 {
  1289.                         for (FormationMap::iterator fi(m_mapActiveFormations.begin()); fi != m_mapActiveFormations.end(); ++fi)
  1290.                         {
  1291.                                 CFormation* pFormation = fi->second;
  1292.                                 if (pFormation && pFormation->GetFormationPoint(refSender))
  1293.                                 {
  1294.                                         CCCPOINT(CAISystem_SendSignal_Formation);
  1295.  
  1296.                                         int s = pFormation->GetSize();
  1297.                                         for (int i = 0; i < s; i++)
  1298.                                         {
  1299.                                                 CAIObject* pMember = pFormation->GetPointOwner(i);
  1300.                                                 if (pMember && (cFilter == SIGNALFILTER_FORMATION || pMember != pSender))
  1301.                                                 {
  1302.                                                         CAIActor* pRecipient = pMember->CastToCAIActor();
  1303.                                                         if (pRecipient)
  1304.                                                                 pRecipient->SetSignal(nSignalId, szText, pSenderEntity, pData ? new AISignalExtraData(*(AISignalExtraData*)pData) : NULL, crcCode);
  1305.                                                 }
  1306.                                         }
  1307.                                         break;
  1308.                                 }
  1309.                         }
  1310.                         break;
  1311.                 }
  1312.         }
  1313. }
  1314.  
  1315. // adds an object to a group
  1316. //
  1317. //-----------------------------------------------------------------------------------------------------------
  1318. void CAISystem::AddToGroup(CAIActor* pObject, int nGroupId)
  1319. {
  1320.         if (!pObject->CastToCPipeUser() && !pObject->CastToCLeader() && !pObject->CastToCAIPlayer())
  1321.                 return;
  1322.  
  1323.         CWeakRef<CAIObject> refObj = GetWeakRef(pObject);
  1324.  
  1325.         if (nGroupId >= 0)
  1326.                 pObject->SetGroupId(nGroupId);
  1327.         else
  1328.                 nGroupId = pObject->GetGroupId();
  1329.  
  1330.         AIObjects::iterator gi;
  1331.         bool found = false;
  1332.         if ((gi = m_mapGroups.find(nGroupId)) != m_mapGroups.end())
  1333.         {
  1334.                 // check whether it was added before
  1335.                 while ((gi != m_mapGroups.end()) && (gi->first == nGroupId))
  1336.                 {
  1337.                         if (gi->second == refObj)
  1338.                         {
  1339.                                 found = true;
  1340.                                 break;
  1341.                         }
  1342.                         ++gi;
  1343.                 }
  1344.         }
  1345.  
  1346.         // in the map - do nothing
  1347.         if (found)
  1348.         {
  1349.                 // Update the group count status and create the group object if necessary.
  1350.                 UpdateGroupStatus(nGroupId);
  1351.                 return;
  1352.         }
  1353.  
  1354.         m_mapGroups.insert(AIObjects::iterator::value_type(nGroupId, refObj));
  1355.  
  1356.         // Update the group count status and create the group object if necessary.
  1357.         UpdateGroupStatus(nGroupId);
  1358.  
  1359.         //group leaders related stuff
  1360.         AIGroupMap::iterator it = m_mapAIGroups.find(nGroupId);
  1361.         if (it != m_mapAIGroups.end())
  1362.         {
  1363.                 if (CLeader* pLeader = pObject->CastToCLeader())
  1364.                 {
  1365.                         //it's a team leader - add him to leaders map
  1366.                         pLeader->SetAIGroup(it->second);
  1367.                         it->second->SetLeader(pLeader);
  1368.                 }
  1369.                 else if (pObject->CastToCPipeUser())
  1370.                 {
  1371.                         // it's a soldier - find the leader of hi's team
  1372.                         it->second->AddMember(pObject);
  1373.                 }
  1374.         }
  1375. }
  1376.  
  1377. // removes specified object from group
  1378. //
  1379. //-----------------------------------------------------------------------------------------------------------
  1380. void CAISystem::RemoveFromGroup(int nGroupID, CAIObject* pObject)
  1381. {
  1382.         AIObjects::iterator gi;
  1383.  
  1384.         for (gi = m_mapGroups.find(nGroupID); gi != m_mapGroups.end(); )
  1385.         {
  1386.                 if (gi->first != nGroupID)
  1387.                         break;
  1388.  
  1389.                 if (gi->second == pObject)
  1390.                 {
  1391.                         m_mapGroups.erase(gi);
  1392.                         break;
  1393.                 }
  1394.                 ++gi;
  1395.         }
  1396.  
  1397.         if (m_mapAIGroups.find(nGroupID) == m_mapAIGroups.end())
  1398.                 return;
  1399.  
  1400.         UpdateGroupStatus(nGroupID);
  1401.  
  1402.         AIGroupMap::iterator it = m_mapAIGroups.find(nGroupID);
  1403.         if (it != m_mapAIGroups.end())
  1404.         {
  1405.                 if (pObject->CastToCLeader())
  1406.                         it->second->SetLeader(0);
  1407.                 else
  1408.                         it->second->RemoveMember(pObject->CastToCAIActor());
  1409.         }
  1410. }
  1411.  
  1412. void CAISystem::UpdateGroupStatus(int nGroupID)
  1413. {
  1414.         AIGroupMap::iterator it = m_mapAIGroups.find(nGroupID);
  1415.         if (it == m_mapAIGroups.end())
  1416.         {
  1417.                 CAIGroup* pNewGroup = new CAIGroup(nGroupID);
  1418.                 m_mapAIGroups.insert(AIGroupMap::iterator::value_type(nGroupID, pNewGroup));
  1419.                 it = m_mapAIGroups.find(nGroupID);
  1420.         }
  1421.  
  1422.         CAIGroup* pGroup = it->second;
  1423.         AIAssert(pGroup);
  1424.         pGroup->UpdateGroupCountStatus();
  1425. }
  1426.  
  1427. // adds an object to a species
  1428. //
  1429. //-----------------------------------------------------------------------------------------------------------
  1430. void CAISystem::AddToFaction(CAIObject* pObject, uint8 factionID)
  1431. {
  1432.         if (factionID != IFactionMap::InvalidFactionID)
  1433.         {
  1434.                 CWeakRef<CAIObject> refObj = GetWeakRef(pObject);
  1435.  
  1436.                 AIObjects::iterator gi;
  1437.  
  1438.                 // (MATT) Bit longwinded, isn't it? {2009/04/01}
  1439.  
  1440.                 if ((gi = m_mapFaction.find(factionID)) != m_mapFaction.end())
  1441.                 {
  1442.                         // check whether it was added before
  1443.                         while ((gi != m_mapFaction.end()) && (gi->first == factionID))
  1444.                         {
  1445.                                 if (gi->second == refObj)
  1446.                                         return;
  1447.                                 ++gi;
  1448.                         }
  1449.                 }
  1450.  
  1451.                 // make sure it is not in with another species already
  1452.                 AIObjects::iterator oi(m_mapFaction.begin());
  1453.                 for (; oi != m_mapFaction.end(); ++oi)
  1454.                 {
  1455.                         if (oi->second == refObj)
  1456.                         {
  1457.                                 m_mapFaction.erase(oi);
  1458.                                 break;
  1459.                         }
  1460.                 }
  1461.  
  1462.                 // it has not been added, add it now
  1463.                 m_mapFaction.insert(AIObjects::iterator::value_type(factionID, refObj));
  1464.         }
  1465. }
  1466.  
  1467. // creates a formation and associates it with a group of agents
  1468. //
  1469. //-----------------------------------------------------------------------------------------------------------
  1470. CFormation* CAISystem::CreateFormation(CWeakRef<CAIObject> refOwner, const char* szFormationName, Vec3 vTargetPos)
  1471. {
  1472.         FormationMap::iterator fi;
  1473.         fi = m_mapActiveFormations.find(refOwner);
  1474.         if (fi == m_mapActiveFormations.end())
  1475.         {
  1476.                 FormationDescriptorMap::iterator di;
  1477.                 di = m_mapFormationDescriptors.find(szFormationName);
  1478.                 if (di != m_mapFormationDescriptors.end())
  1479.                 {
  1480.                         CCCPOINT(CAISystem_CreateFormation);
  1481.  
  1482.                         CFormation* pFormation = new CFormation();
  1483.                         pFormation->Create(di->second, refOwner, vTargetPos);
  1484.                         m_mapActiveFormations.insert(FormationMap::iterator::value_type(refOwner, pFormation));
  1485.                         return pFormation;
  1486.                 }
  1487.         }
  1488.         else
  1489.                 return (fi->second);
  1490.         return 0;
  1491. }
  1492.  
  1493. string CAISystem::GetFormationNameFromCRC32(unsigned int nCrc32ForFormationName) const
  1494. {
  1495.         FormationDescriptorMap::const_iterator currentFormation = m_mapFormationDescriptors.begin();
  1496.         FormationDescriptorMap::const_iterator end = m_mapFormationDescriptors.end();
  1497.         for (; currentFormation != end; ++currentFormation)
  1498.         {
  1499.                 if (currentFormation->second.m_nNameCRC32 == nCrc32ForFormationName)
  1500.                         return currentFormation->first;
  1501.         }
  1502.  
  1503.         return "";
  1504. }
  1505.  
  1506. // return a formation by id (used for serialization)
  1507. //
  1508. //-----------------------------------------------------------------------------------------------------------
  1509. CFormation* CAISystem::GetFormation(CFormation::TFormationID id)
  1510. {
  1511.         for (FormationMap::const_iterator it = m_mapActiveFormations.begin(), end = m_mapActiveFormations.end(); it != end; ++it)
  1512.         {
  1513.                 if (it->second->GetId() == id)
  1514.                         return it->second;
  1515.         }
  1516.  
  1517.         return NULL;
  1518. }
  1519.  
  1520. // change the current formation for the given group
  1521. //
  1522. //-----------------------------------------------------------------------------------------------------------
  1523. bool CAISystem::ChangeFormation(IAIObject* pOwner, const char* szFormationName, float fScale)
  1524. {
  1525.         if (pOwner)
  1526.         {
  1527.                 CFormation* pFormation = ((CAIObject*)pOwner)->m_pFormation;
  1528.                 if (pFormation)
  1529.                 {
  1530.                         FormationDescriptorMap::iterator di;
  1531.                         di = m_mapFormationDescriptors.find(szFormationName);
  1532.                         if (di != m_mapFormationDescriptors.end())
  1533.                         {
  1534.                                 CCCPOINT(CAISystem_ChangeFormation);
  1535.  
  1536.                                 pFormation->Change(di->second, fScale);
  1537.                                 return true;
  1538.                         }
  1539.                 }
  1540.         }
  1541.         return false;
  1542. }
  1543.  
  1544. // scale the current formation for the given group
  1545. //
  1546. //-----------------------------------------------------------------------------------------------------------
  1547. bool CAISystem::ScaleFormation(IAIObject* pOwner, float fScale)
  1548. {
  1549.         CWeakRef<CAIObject> refOwner = GetWeakRef(static_cast<CAIObject*>(pOwner));
  1550.         FormationMap::iterator fi;
  1551.         fi = m_mapActiveFormations.find(refOwner);
  1552.         if (fi != m_mapActiveFormations.end())
  1553.         {
  1554.                 CFormation* pFormation = fi->second;
  1555.                 if (pFormation)
  1556.                 {
  1557.                         CCCPOINT(CAISystem_ScaleFormation);
  1558.  
  1559.                         pFormation->SetScale(fScale);
  1560.                         return true;
  1561.                 }
  1562.         }
  1563.         return false;
  1564. }
  1565.  
  1566. // scale the current formation for the given group
  1567. //
  1568. //-----------------------------------------------------------------------------------------------------------
  1569. bool CAISystem::SetFormationUpdate(IAIObject* pOwner, bool bUpdate)
  1570. {
  1571.         CWeakRef<CAIObject> refOwner = GetWeakRef(static_cast<CAIObject*>(pOwner));
  1572.         FormationMap::iterator fi;
  1573.         fi = m_mapActiveFormations.find(refOwner);
  1574.         if (fi != m_mapActiveFormations.end())
  1575.         {
  1576.                 CFormation* pFormation = fi->second;
  1577.                 if (pFormation)
  1578.                 {
  1579.                         pFormation->SetUpdate(bUpdate);
  1580.                         return true;
  1581.                 }
  1582.         }
  1583.         return false;
  1584. }
  1585.  
  1586. // check if puppet and vehicle are in the same formation
  1587. //
  1588. //-----------------------------------------------------------------------------------------------------------
  1589. bool CAISystem::SameFormation(const CPuppet* pHuman, const CAIVehicle* pVehicle)
  1590. {
  1591.         if (pHuman->IsHostile(pVehicle))
  1592.                 return false;
  1593.         for (FormationMap::iterator fi(m_mapActiveFormations.begin()); fi != m_mapActiveFormations.end(); ++fi)
  1594.         {
  1595.                 CFormation* pFormation = fi->second;
  1596.                 if (pFormation->GetFormationPoint(GetWeakRef(pHuman)))
  1597.                 {
  1598.                         CAIObject* pFormationOwner(pFormation->GetPointOwner(0));
  1599.                         if (!pFormationOwner)
  1600.                                 return false;
  1601.                         if (pFormationOwner == pVehicle->GetAttentionTarget())
  1602.                         {
  1603.                                 CCCPOINT(CAISystem_SameFormation);
  1604.                                 return true;
  1605.                         }
  1606.                         return false;
  1607.                 }
  1608.         }
  1609.         return false;
  1610. }
  1611.  
  1612. // Resets all agent states to initial
  1613. //
  1614. //-----------------------------------------------------------------------------------------------------------
  1615. void CAISystem::Reset(IAISystem::EResetReason reason)
  1616. {
  1617.         MEMSTAT_LABEL("CAISystem::Reset");
  1618.  
  1619.         // Faction Map needs to reset and be present even when AISystem is disabled (i.e. multiplayer)
  1620.         {
  1621.                 switch (reason)
  1622.                 {
  1623.                 case RESET_LOAD_LEVEL:
  1624.                         gAIEnv.pFactionMap->Reload();
  1625.                         break;
  1626.                 case RESET_UNLOAD_LEVEL:
  1627.                         gAIEnv.pFactionMap->Clear();
  1628.                         break;
  1629.                 default:
  1630.                         break;
  1631.                 }
  1632.         }
  1633.  
  1634.         // Don't reset if disabled, unless we're unloading the level in which case allow the cleanup to go ahead
  1635.         if (!IsEnabled() && reason != RESET_UNLOAD_LEVEL)
  1636.         {
  1637.                 if (reason == RESET_LOAD_LEVEL)
  1638.                 {
  1639.                         /*
  1640.  
  1641.                            TODO : For games different from HUNT we will need to take a look at the memory leaks of the AI System
  1642.                            when the level is loaded without forcing the RESET_UNLOAD_LEVEL
  1643.  
  1644.                            // -------------------------------------------------------------------------------------------------------------------------
  1645.  
  1646.                            // Make sure RESET_UNLOAD_LEVEL is done.
  1647.                            // Currently if going to multi player without going to single player first there are lots of memory leaks if this isn't done
  1648.                            // due to allocations in CAISystem::Init().
  1649.  
  1650.                            // Don't do this since we use AI in multiplayer in Hunt, and this will cause
  1651.                            // it to not be initialized.
  1652.                            reason = RESET_UNLOAD_LEVEL;
  1653.  
  1654.                          */
  1655.                 }
  1656.                 else
  1657.                 {
  1658.                         return;
  1659.                 }
  1660.         }
  1661.  
  1662.         MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "AI Reset");
  1663.         LOADING_TIME_PROFILE_SECTION;
  1664.  
  1665.         switch (reason)
  1666.         {
  1667.         case RESET_LOAD_LEVEL:
  1668. #if CAPTURE_REPLAY_LOG
  1669.                 CryGetIMemReplay()->AddLabelFmt("AILoad");
  1670. #endif
  1671.                 if (!gAIEnv.pTacticalPointSystem)
  1672.                 {
  1673.                         gAIEnv.pTacticalPointSystem = new CTacticalPointSystem();
  1674.                         g_flyHelpersTacticalLanguageExtender.Initialize();
  1675.                 }
  1676.                 if (!gAIEnv.pGraph)
  1677.                 {
  1678.                         gAIEnv.pGraph = m_pGraph = new CGraph;
  1679.                 }
  1680.                 if (!gAIEnv.pNavigation)
  1681.                 {
  1682.                         gAIEnv.pNavigation = m_pNavigation = new CNavigation(gEnv->pSystem);
  1683.                         m_pNavigation->Init();
  1684.                 }
  1685.                 if (!gAIEnv.pCoverSystem)
  1686.                 {
  1687.                         gAIEnv.pCoverSystem = new CCoverSystem("Scripts/AI/Cover.xml");
  1688.                 }
  1689.                 if (!gAIEnv.pNavigationSystem)
  1690.                 {
  1691.                         gAIEnv.pNavigationSystem = new NavigationSystem("Scripts/AI/Navigation.xml");
  1692.                 }
  1693.                 if (!gAIEnv.pMNMPathfinder)
  1694.                 {
  1695.                         gAIEnv.pPathfinderNavigationSystemUser = new MNM::PathfinderNavigationSystemUser;
  1696.                         gAIEnv.pMNMPathfinder = gAIEnv.pPathfinderNavigationSystemUser->GetPathfinderImplementation();
  1697.                         assert(gAIEnv.pNavigationSystem);
  1698.                         gAIEnv.pNavigationSystem->RegisterUser(gAIEnv.pPathfinderNavigationSystemUser, "PathfinderExtension");
  1699.                 }
  1700.                 if (!gAIEnv.pVisionMap)
  1701.                 {
  1702.                         gAIEnv.pVisionMap = new CVisionMap();
  1703.                 }
  1704.                 if (!gAIEnv.pGroupManager)
  1705.                 {
  1706.                         gAIEnv.pGroupManager = new CGroupManager();
  1707.                 }
  1708.                 if (!gAIEnv.pAIActionManager)
  1709.                 {
  1710.                         gAIEnv.pAIActionManager = m_pAIActionManager = new CAIActionManager();
  1711.                 }
  1712.                 if (!gAIEnv.pSmartObjectManager)
  1713.                 {
  1714.                         gAIEnv.pSmartObjectManager = m_pSmartObjectManager = new CSmartObjectManager();
  1715.                 }
  1716.                 if (!gAIEnv.pRayCaster)
  1717.                 {
  1718.                         gAIEnv.pRayCaster = new SAIEnvironment::GlobalRayCaster;
  1719.                         gAIEnv.pRayCaster->SetQuota(gAIEnv.CVars.RayCasterQuota);
  1720.                 }
  1721.                 if (!gAIEnv.pIntersectionTester)
  1722.                 {
  1723.                         gAIEnv.pIntersectionTester = new SAIEnvironment::GlobalIntersectionTester;
  1724.                         gAIEnv.pIntersectionTester->SetQuota(gAIEnv.CVars.IntersectionTesterQuota);
  1725.                 }
  1726.                 if (!gAIEnv.pMovementSystem)
  1727.                 {
  1728.                         gAIEnv.pMovementSystem = MovementSystemCreator().CreateMovementSystem();
  1729.                 }
  1730.                 if (!gAIEnv.pActorLookUp)
  1731.                 {
  1732.                         gAIEnv.pActorLookUp = new ActorLookUp();
  1733.                 }
  1734.                 if (!gAIEnv.pWalkabilityCacheManager)
  1735.                 {
  1736.                         gAIEnv.pWalkabilityCacheManager = new WalkabilityCacheManager();
  1737.                 }
  1738.  
  1739.                 if (gAIEnv.pTargetTrackManager)
  1740.                 {
  1741.                         gAIEnv.pTargetTrackManager->Reset(reason);
  1742.                 }
  1743.                 if (gAIEnv.pPerceptionManager)
  1744.                 {
  1745.                         gAIEnv.pPerceptionManager->Reset(reason);
  1746.                 }
  1747.  
  1748.                 m_bInitialized = true;
  1749.  
  1750.                 return;
  1751.  
  1752.         case RESET_UNLOAD_LEVEL:
  1753.                 if (!gEnv->IsEditor())
  1754.                 {
  1755.                         if (gAIEnv.pTargetTrackManager)
  1756.                                 gAIEnv.pTargetTrackManager->Reset(RESET_UNLOAD_LEVEL);
  1757.  
  1758. #if !defined(_RELEASE)
  1759.                         if (gAIEnv.pCodeCoverageGUI)
  1760.                                 gAIEnv.pCodeCoverageGUI->Reset(RESET_UNLOAD_LEVEL);
  1761. #endif
  1762.  
  1763.                         for (AIGroupMap::iterator it = m_mapAIGroups.begin(); it != m_mapAIGroups.end(); ++it)
  1764.                                 delete it->second;
  1765.                         stl::free_container(m_mapAIGroups);
  1766.  
  1767.                         SAFE_DELETE(m_pGraph);
  1768.                         gAIEnv.pGraph = NULL;
  1769.                         SAFE_DELETE(m_pNavigation);
  1770.                         gAIEnv.pNavigation = NULL;
  1771.                         gAIEnv.pNavigationSystem->UnRegisterUser(gAIEnv.pPathfinderNavigationSystemUser);
  1772.                         gAIEnv.pMNMPathfinder = NULL;
  1773.                         SAFE_DELETE(gAIEnv.pPathfinderNavigationSystemUser);
  1774.                         SAFE_DELETE(gAIEnv.pVisionMap);
  1775.                         SAFE_DELETE(gAIEnv.pCoverSystem);
  1776.                         SAFE_DELETE(gAIEnv.pNavigationSystem);
  1777.                         SAFE_DELETE(gAIEnv.pGroupManager);
  1778.                         SAFE_DELETE(m_pAIActionManager);
  1779.                         gAIEnv.pAIActionManager = NULL;
  1780.                         SAFE_DELETE(m_pSmartObjectManager);
  1781.                         gAIEnv.pSmartObjectManager = NULL;
  1782.                         SAFE_DELETE(gAIEnv.pRayCaster);
  1783.                         SAFE_DELETE(gAIEnv.pIntersectionTester);
  1784.                         SAFE_DELETE(gAIEnv.pActorLookUp);
  1785.                         SAFE_DELETE(gAIEnv.pWalkabilityCacheManager);
  1786.                         SAFE_DELETE(gAIEnv.pTacticalPointSystem);
  1787.                         m_mapAuxSignalsFired.clear();
  1788.                         stl::free_container(m_sWorkingFolder);
  1789.                         stl::free_container(m_priorityTargets);
  1790.                         gAIEnv.pPerceptionManager->Reset(reason);
  1791.                         gAIEnv.pCommunicationManager->Reset();
  1792.                         m_PipeManager.ClearAllGoalPipes();
  1793.                         CPuppet::ClearStaticData();
  1794.                         stl::free_container(m_walkabilityPhysicalEntities);
  1795.                         if (m_walkabilityGeometryBox)
  1796.                         {
  1797.                                 m_walkabilityGeometryBox->Release();
  1798.                                 m_walkabilityGeometryBox = NULL;
  1799.                         }
  1800.  
  1801.                         gAIEnv.pCollisionAvoidanceSystem->Reset(true);
  1802.  
  1803.                         CleanupAICollision();
  1804.                         ClearAIObjectIteratorPools();
  1805.  
  1806.                         CPathObstacles::ResetOfStaticData();
  1807.                         AISignalExtraData::CleanupPool();
  1808.  
  1809.                         stl::free_container(m_tmpFullUpdates);
  1810.                         stl::free_container(m_tmpDryUpdates);
  1811.                         stl::free_container(m_tmpAllUpdates);
  1812.  
  1813. #ifdef CRYAISYSTEM_DEBUG
  1814.                         stl::free_container(m_DEBUG_fakeTracers);
  1815.                         stl::free_container(m_DEBUG_fakeHitEffect);
  1816.                         stl::free_container(m_DEBUG_fakeDamageInd);
  1817. #endif //CRYAISYSTEM_DEBUG
  1818.  
  1819.                         gAIEnv.pBehaviorTreeManager->Reset();
  1820.                         gAIEnv.pGraftManager->Reset();
  1821.                         gAIEnv.pMovementSystem->Reset();
  1822.  
  1823.                         m_bInitialized = false;
  1824.  
  1825.                         MEMSTAT_LABEL("AIUnload");
  1826.                 }
  1827.                 return;
  1828.         }
  1829.  
  1830.         AILogEvent("CAISystem::Reset %d", reason);
  1831.         m_bUpdateSmartObjects = false;
  1832.  
  1833.         // Notify listeners
  1834.         for (SystemListenerSet::iterator it = m_setSystemListeners.begin(); it != m_setSystemListeners.end(); ++it)
  1835.         {
  1836.                 (*it)->OnEvent(IAISystemListener::eAISE_Reset);
  1837.         }
  1838.  
  1839.         if (gAIEnv.pTargetTrackManager)
  1840.                 gAIEnv.pTargetTrackManager->Reset(reason);
  1841.  
  1842. #ifdef CRYAISYSTEM_DEBUG
  1843.         m_Recorder.OnReset(reason);
  1844. #endif //CRYAISYSTEM_DEBUG
  1845.  
  1846.         if (gAIEnv.pCoverSystem)
  1847.                 gAIEnv.pCoverSystem->Reset();
  1848.  
  1849.         if (gAIEnv.pMovementSystem)
  1850.                 gAIEnv.pMovementSystem->Reset();
  1851.  
  1852.         // It would be much better to have this at the end of Reset, when state is minimal
  1853.         // However there are various returns below that stop it being hit
  1854.  
  1855.         SetAIHacksConfiguration();
  1856.  
  1857.         // May need to make calls here to get those settings reflected in the system
  1858.  
  1859.         if (reason != RESET_ENTER_GAME)
  1860.                 // Reset Interest System
  1861.                 GetCentralInterestManager()->Reset();
  1862.  
  1863.         m_lightManager.Reset();
  1864.  
  1865. #if !defined(_RELEASE)
  1866.         gAIEnv.pCodeCoverageGUI->Reset(reason);
  1867. #endif
  1868.  
  1869.         // reset the groups.
  1870.         for (AIGroupMap::iterator it = m_mapAIGroups.begin(); it != m_mapAIGroups.end(); ++it)
  1871.                 it->second->Reset();
  1872.  
  1873.         for (int i = 0; i < NUM_ALERTNESS_COUNTERS; i++)
  1874.                 m_AlertnessCounters[i] = 0;
  1875.  
  1876.         if (!m_bInitialized)
  1877.                 return;
  1878.  
  1879.         const char* sStatsTarget = gAIEnv.CVars.StatsTarget;
  1880.         if ((*sStatsTarget != '\0') && (stricmp("none", sStatsTarget) != 0))
  1881.                 Record(NULL, IAIRecordable::E_RESET, NULL);
  1882.  
  1883.         if (m_pSmartObjectManager->IsInitialized())
  1884.         {
  1885.                 m_pAIActionManager->Reset();
  1886.  
  1887.                 // If CAISystem::Reset() was called from CAISystem::Shutdown() IEntitySystem is already deleted
  1888.                 if (gEnv->pEntitySystem)
  1889.                 {
  1890.                         if (reason == IAISystem::RESET_ENTER_GAME || reason == IAISystem::RESET_INTERNAL_LOAD)
  1891.                         {
  1892.                                 m_pSmartObjectManager->SoftReset();
  1893.                         }
  1894.                 }
  1895.         }
  1896.         else
  1897.         {
  1898.                 // If CAISystem::Reset() was called from CAISystem::Shutdown() IEntitySystem is already deleted
  1899.                 if (gEnv->pEntitySystem)
  1900.                         InitSmartObjects();
  1901.         }
  1902.  
  1903.         //m_mapDEBUGTiming.clear();
  1904.  
  1905.         AIObjectOwners::iterator ai;
  1906.  
  1907.         EObjectResetType objectResetType = AIOBJRESET_INIT;
  1908.         switch (reason)
  1909.         {
  1910.         case RESET_EXIT_GAME:
  1911.                 objectResetType = AIOBJRESET_SHUTDOWN;
  1912.                 break;
  1913.         case RESET_INTERNAL:
  1914.         case RESET_INTERNAL_LOAD:
  1915.         case RESET_ENTER_GAME:
  1916.         default:
  1917.                 objectResetType = AIOBJRESET_INIT;
  1918.                 break;
  1919.         }
  1920.  
  1921.         const bool editorToGameMode = (gEnv->IsEditor() && reason == RESET_ENTER_GAME);
  1922.         if (editorToGameMode)
  1923.         {
  1924.                 gAIEnv.pBehaviorTreeManager->Reset();
  1925.                 gAIEnv.pGraftManager->Reset();
  1926.  
  1927.                 CallReloadTPSQueriesScript();
  1928.         }
  1929.  
  1930.         if (reason == RESET_LOAD_LEVEL)
  1931.         {
  1932.                 CallReloadTPSQueriesScript();
  1933.         }
  1934.  
  1935.         for (ai = gAIEnv.pAIObjectManager->m_Objects.begin(); ai != gAIEnv.pAIObjectManager->m_Objects.end(); ++ai)
  1936.         {
  1937.                 // Strong, so always valid
  1938.                 CAIObject* pObject = ai->second.GetAIObject();
  1939.                 pObject->Reset(objectResetType);
  1940.  
  1941. #ifdef CRYAISYSTEM_DEBUG
  1942.                 // Reset the AI recordable stuff when entering game mode.
  1943.                 if (reason == IAISystem::RESET_ENTER_GAME)
  1944.                 {
  1945.                         CTimeValue startTime = gEnv->pTimer->GetFrameStartTime();
  1946.                         CRecorderUnit* pRecord = static_cast<CRecorderUnit*>(pObject->GetAIDebugRecord());
  1947.                         if (pRecord)
  1948.                         {
  1949.                                 pRecord->ResetStreams(startTime);
  1950.                         }
  1951.                 }
  1952. #endif //CRYAISYSTEM_DEBUG
  1953.  
  1954.         }
  1955.  
  1956. #ifdef CRYAISYSTEM_DEBUG
  1957.  
  1958.         // Reset the recorded trajectory.
  1959.         m_lastStatsTargetTrajectoryPoint.Set(0, 0, 0);
  1960.         m_lstStatsTargetTrajectory.clear();
  1961.  
  1962.         m_DEBUG_fakeTracers.clear();
  1963.         m_DEBUG_fakeHitEffect.clear();
  1964.         m_DEBUG_fakeDamageInd.clear();
  1965.         m_DEBUG_screenFlash = 0.0f;
  1966.  
  1967. #endif //CRYAISYSTEM_DEBUG
  1968.  
  1969.         if (!m_mapActiveFormations.empty())
  1970.         {
  1971.                 FormationMap::iterator fi;
  1972.                 for (fi = m_mapActiveFormations.begin(); fi != m_mapActiveFormations.end(); ++fi)
  1973.                 {
  1974.                         CFormation* pFormation = fi->second;
  1975.                         if (pFormation)
  1976.                         {
  1977.                                 delete pFormation;
  1978.                         }
  1979.                 }
  1980.                 m_mapActiveFormations.clear();
  1981.         }
  1982.  
  1983.         if (reason == RESET_EXIT_GAME)
  1984.         {
  1985.                 gAIEnv.pTacticalPointSystem->Reset();
  1986.                 gAIEnv.pCommunicationManager->Reset();
  1987.                 gAIEnv.pSelectionTreeManager->Reset();
  1988.                 gAIEnv.pVisionMap->Reset();
  1989.                 gAIEnv.pFactionMap->Reload();
  1990.  
  1991.                 gAIEnv.pRayCaster->ResetContentionStats();
  1992.                 gAIEnv.pIntersectionTester->ResetContentionStats();
  1993.         }
  1994.  
  1995.         gAIEnv.pGroupManager->Reset(objectResetType);
  1996.  
  1997.         ClearAIObjectIteratorPools();
  1998.         m_pNavigation->Reset(reason);
  1999.         gAIEnv.pNavigationSystem->Reset();
  2000.  
  2001.         m_pGraph->ClearMarks();
  2002.         m_pGraph->Reset();
  2003.  
  2004.         CPathObstacles::ResetOfStaticData();
  2005.  
  2006.         m_dynHideObjectManager.Reset();
  2007.  
  2008.         m_mapAuxSignalsFired.clear();
  2009.  
  2010.         m_mapBeacons.clear();
  2011.  
  2012.         // Remove temporary shapes and re-enable all shapes.
  2013.         for (ShapeMap::iterator it = m_mapGenericShapes.begin(); it != m_mapGenericShapes.end(); )
  2014.         {
  2015.                 // Enable
  2016.                 it->second.enabled = true;
  2017.                 // Remove temp
  2018.                 if (it->second.temporary)
  2019.                         m_mapGenericShapes.erase(it++);
  2020.                 else
  2021.                         ++it;
  2022.         }
  2023.  
  2024.         m_pSmartObjectManager->ResetBannedSOs();
  2025.  
  2026.         m_lastAmbientFireUpdateTime.SetSeconds(-10.0f);
  2027.         m_lastExpensiveAccessoryUpdateTime.SetSeconds(-10.0f);
  2028.         m_lastVisBroadPhaseTime.SetSeconds(-10.0f);
  2029.         m_lastGroupUpdateTime.SetSeconds(-10.0f);
  2030.  
  2031.         m_delayedExpAccessoryUpdates.clear();
  2032.  
  2033.         gAIEnv.pPerceptionManager->Reset(reason);
  2034.  
  2035.         ResetAIActorSets(reason != RESET_ENTER_GAME);
  2036.  
  2037.         DebugOutputObjects("End of reset");
  2038.  
  2039. #ifdef CALIBRATE_STOPPER
  2040.         AILogAlways("Calculation stopper calibration:");
  2041.         for (CCalculationStopper::TMapCallRate::const_iterator it = CCalculationStopper::m_mapCallRate.begin(); it != CCalculationStopper::m_mapCallRate.end(); ++it)
  2042.         {
  2043.                 const std::pair<unsigned, float>& result = it->second;
  2044.                 const string& name = it->first;
  2045.                 float rate = result.second > 0.0f ? result.first / result.second : -1.0f;
  2046.                 AILogAlways("%s calls = %d time = %6.2f sec call-rate = %7.2f", f
  2047.                             name.c_str(), result.first, result.second, rate);
  2048.         }
  2049. #endif
  2050.  
  2051. #ifdef CRYAISYSTEM_DEBUG
  2052.         if (gAIEnv.pBubblesSystem)
  2053.                 gAIEnv.pBubblesSystem->Reset();
  2054. #endif
  2055.  
  2056.         if (reason == IAISystem::RESET_ENTER_GAME || reason == IAISystem::RESET_UNLOAD_LEVEL)
  2057.         {
  2058.                 gAIEnv.pSequenceManager->Reset();
  2059.                 gAIEnv.pClusterDetector->Reset();
  2060.         }
  2061.  
  2062.         if (reason == RESET_EXIT_GAME || reason == RESET_UNLOAD_LEVEL)
  2063.         {
  2064.                 gAIEnv.pBehaviorTreeManager->Reset();
  2065.                 gAIEnv.pGraftManager->Reset();
  2066.         }
  2067. }
  2068.  
  2069. //-----------------------------------------------------------------------------------------------------------
  2070. int CAISystem::GetGroupCount(int nGroupID, int flags, int type)
  2071. {
  2072.         if (type == 0)
  2073.         {
  2074.                 AIGroupMap::iterator it = m_mapAIGroups.find(nGroupID);
  2075.                 if (it == m_mapAIGroups.end())
  2076.                         return 0;
  2077.  
  2078.                 return it->second->GetGroupCount(flags);
  2079.         }
  2080.         else
  2081.         {
  2082.                 int count = 0;
  2083.                 int countEnabled = 0;
  2084.                 for (AIObjects::iterator it = m_mapGroups.find(nGroupID); it != m_mapGroups.end() && it->first == nGroupID; ++it)
  2085.                 {
  2086.                         CAIObject* pObject = it->second.GetAIObject();
  2087.                         ;
  2088.                         if (pObject->GetType() == type)
  2089.                         {
  2090.                                 if (pObject->IsEnabled())
  2091.                                         countEnabled++;
  2092.                                 count++;
  2093.                         }
  2094.                 }
  2095.  
  2096.                 if (flags & IAISystem::GROUP_MAX)
  2097.                 {
  2098.                         AIWarning("GetGroupCount does not support specified type and max count to be used at the same time." /*, type*/);
  2099.                         flags &= ~IAISystem::GROUP_MAX;
  2100.                 }
  2101.  
  2102.                 if (flags == 0 || flags == IAISystem::GROUP_ALL)
  2103.                         return count;
  2104.                 else if (flags == IAISystem::GROUP_ENABLED)
  2105.                         return countEnabled;
  2106.         }
  2107.  
  2108.         return 0;
  2109. }
  2110.  
  2111. // gets the I-th agent in a specified group
  2112. //
  2113. //-----------------------------------------------------------------------------------------------------------
  2114. IAIObject* CAISystem::GetGroupMember(int nGroupID, int nIndex, int flags, int type)
  2115. {
  2116.         if (nIndex < 0)
  2117.                 return NULL;
  2118.  
  2119.         bool bOnlyEnabled = false;
  2120.         if (flags & IAISystem::GROUP_ENABLED)
  2121.                 bOnlyEnabled = true;
  2122.  
  2123.         AIObjects::iterator gi = m_mapGroups.find(nGroupID);
  2124.         for (; gi != m_mapGroups.end() && nIndex >= 0; ++gi)
  2125.         {
  2126.                 CAIObject* pObject = gi->second.GetAIObject();
  2127.                 if (gi->first != nGroupID)
  2128.                         return NULL;
  2129.                 if ((pObject != NULL) && pObject->GetType() != AIOBJECT_LEADER && // skip leaders
  2130.                     (!type || pObject->GetType() == type) &&
  2131.                     (!bOnlyEnabled || pObject->IsEnabled()))
  2132.                 {
  2133.                         if (0 == nIndex)
  2134.                                 return pObject;
  2135.                         --nIndex;
  2136.                         // (MATT) Why decrement index? {2009/03/26}
  2137.                 }
  2138.         }
  2139.         return NULL;
  2140. }
  2141.  
  2142. //====================================================================
  2143. // GetLeader
  2144. //====================================================================
  2145. CLeader* CAISystem::GetLeader(int nGroupID)
  2146. {
  2147.         AIGroupMap::iterator it = m_mapAIGroups.find(nGroupID);
  2148.         if (it != m_mapAIGroups.end())
  2149.                 return it->second->GetLeader();
  2150.         return 0;
  2151. }
  2152.  
  2153. CLeader* CAISystem::GetLeader(const CAIActor* pSoldier)
  2154. {
  2155.         return (pSoldier ? GetLeader(pSoldier->GetGroupId()) : NULL);
  2156. }
  2157.  
  2158. //====================================================================
  2159. // SetLeader
  2160. //====================================================================
  2161. void CAISystem::SetLeader(IAIObject* pObject)
  2162. {
  2163.         // can't make disabled/dead puppet a leader
  2164.         if (!pObject->IsEnabled() || pObject->GetProxy() && pObject->GetProxy()->IsDead())
  2165.                 return;
  2166.         CAIActor* pActor = pObject->CastToCAIActor();
  2167.         if (!pActor)
  2168.                 return;
  2169.         int groupid = pActor->GetGroupId();
  2170.         CLeader* pLeader = GetLeader(groupid);
  2171.         if (!pLeader)
  2172.         {
  2173.                 pLeader = (CLeader*) m_AIObjectManager.CreateAIObject(AIObjectParams(AIOBJECT_LEADER, pObject));
  2174.                 CAIGroup* pGroup = GetAIGroup(groupid);
  2175.                 if (pGroup)
  2176.                         pGroup->SetLeader(pLeader);
  2177.         }
  2178.         else
  2179.         {
  2180.                 pLeader->SetAssociation(GetWeakRef((CAIObject*)pObject));
  2181.                 CCCPOINT(CAISystem_SetLeader);
  2182.         }
  2183.  
  2184.         return;
  2185. }
  2186.  
  2187. //====================================================================
  2188. // SetLeader
  2189. //====================================================================
  2190. CLeader* CAISystem::CreateLeader(int nGroupID)
  2191. {
  2192.         CLeader* pLeader = GetLeader(nGroupID);
  2193.         if (pLeader)
  2194.                 return NULL;
  2195.         CAIGroup* pGroup = GetAIGroup(nGroupID);
  2196.         if (!pGroup)
  2197.                 return NULL;
  2198.         TUnitList& unitsList = pGroup->GetUnits();
  2199.         if (unitsList.empty())
  2200.                 return NULL;
  2201.  
  2202.         CAIActor* pLeaderActor = (unitsList.begin())->m_refUnit.GetAIObject();
  2203.         pLeader = (CLeader*) m_AIObjectManager.CreateAIObject(AIObjectParams(AIOBJECT_LEADER, pLeaderActor));
  2204.         pGroup->SetLeader(pLeader);
  2205.         return pLeader;
  2206. }
  2207.  
  2208. //====================================================================
  2209. // GetAIGroup
  2210. //====================================================================
  2211. CAIGroup* CAISystem::GetAIGroup(int nGroupID)
  2212. {
  2213.         AIGroupMap::iterator it = m_mapAIGroups.find(nGroupID);
  2214.         if (it != m_mapAIGroups.end())
  2215.                 return it->second;
  2216.         return 0;
  2217. }
  2218.  
  2219. IAIGroup* CAISystem::GetIAIGroup(int nGroupID)
  2220. {
  2221.         return (IAIGroup*)GetAIGroup(nGroupID);
  2222. }
  2223.  
  2224. //====================================================================
  2225. // ReadAreasFromFile
  2226. //====================================================================
  2227. #if defined(SEG_WORLD)
  2228. void CAISystem::ReadAreasFromFile(const char* fileNameAreas, const Vec3& vSegmentOffset)
  2229. #else
  2230. void CAISystem::ReadAreasFromFile(const char* fileNameAreas)
  2231. #endif
  2232. {
  2233.         MEMSTAT_CONTEXT_FMT(EMemStatContextTypes::MSC_Navigation, 0, "Areas (%s)", fileNameAreas);
  2234.         LOADING_TIME_PROFILE_SECTION
  2235.  
  2236.         CCryBufferedFileReader file;
  2237.         if (false != file.Open(fileNameAreas, "rb"))
  2238.         {
  2239.                 int iNumber = 0;
  2240.                 file.ReadType(&iNumber);
  2241.  
  2242.                 if (iNumber == 18)
  2243.                 {
  2244.                         AIWarning("AI area file version 18 found - suitable only for subsequent export");
  2245.                 }
  2246.                 else if (iNumber < BAI_AREA_FILE_VERSION_READ)
  2247.                 {
  2248.                         AIError("Incompatible AI area file version - found %d, expected range [%d,%d] - regenerate triangulation [Design bug]", iNumber, BAI_AREA_FILE_VERSION_READ, BAI_AREA_FILE_VERSION_WRITE);
  2249.                         file.Close();
  2250.                         return;
  2251.                 }
  2252.  
  2253.                 if (iNumber < BAI_AREA_FILE_VERSION_WRITE)
  2254.                         m_pNavigation->ReadAreasFromFile_Old(file, iNumber);
  2255.                 else
  2256.                 {
  2257. #if defined(SEG_WORLD)
  2258.                         m_pNavigation->ReadAreasFromFile(file, iNumber, vSegmentOffset);
  2259. #else
  2260.                         m_pNavigation->ReadAreasFromFile(file, iNumber);
  2261. #endif
  2262.                 }
  2263.  
  2264. #if defined(SEG_WORLD)
  2265.                 // don't flush all areas here if we're in segmented world
  2266.                 if (!gEnv->p3DEngine->GetSegmentsManager()) //@TODO: make seg-world manager available from gEnv.
  2267.                         FlushAllAreas();
  2268. #endif
  2269.  
  2270.                 unsigned numAreas;
  2271.  
  2272.                 // Read generic shapes
  2273.                 if (iNumber > 15)
  2274.                 {
  2275.                         file.ReadType(&numAreas);
  2276.                         // vague sanity check
  2277.                         AIAssert(numAreas < 1000000);
  2278.                         for (unsigned iArea = 0; iArea < numAreas; ++iArea)
  2279.                         {
  2280.                                 ListPositions lp;
  2281.                                 string name;
  2282. #if defined(SEG_WORLD)
  2283.                                 ReadPolygonArea(file, iNumber, name, lp, vSegmentOffset);
  2284. #else
  2285.                                 ReadPolygonArea(file, iNumber, name, lp);
  2286. #endif
  2287.  
  2288.                                 int navType, type;
  2289.                                 file.ReadType(&navType);
  2290.                                 file.ReadType(&type);
  2291.                                 float height = 0;
  2292.                                 int lightLevel = 0;
  2293.                                 if (iNumber >= 18)
  2294.                                 {
  2295.                                         file.ReadType(&height);
  2296.                                         file.ReadType(&lightLevel);
  2297.                                 }
  2298.  
  2299.                                 if (m_mapGenericShapes.find(name) != m_mapGenericShapes.end())
  2300.                                         AIError("CAISystem::ReadAreasFromFile: Shape '%s' already exists, please rename the path and reexport.", name.c_str());
  2301.                                 else
  2302.                                         m_mapGenericShapes.insert(ShapeMap::iterator::value_type(name, SShape(lp, false, (IAISystem::ENavigationType)navType, type, true, height, (EAILightLevel)lightLevel)));
  2303.                         }
  2304.                 }
  2305.                 file.Close();
  2306.         }
  2307.         else
  2308.         {
  2309.                 AIWarning("Unable to open areas file %s", fileNameAreas);
  2310.         }
  2311. }
  2312.  
  2313. // // loads the triangulation for this level and mission
  2314. //
  2315. //-----------------------------------------------------------------------------------------------------------
  2316. void CAISystem::LoadNavigationData(const char* szLevel, const char* szMission, const EAILoadDataFlags loadDataFlags /*= eAILoadDataFlag_AllSystems*/)
  2317. {
  2318.         MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Navigation, 0, "AI Navigation");
  2319.  
  2320.         LOADING_TIME_PROFILE_SECTION(GetISystem());
  2321.  
  2322.         if (!IsEnabled())
  2323.                 return;
  2324.  
  2325.         if (!szLevel || !szMission)
  2326.                 return;
  2327.  
  2328.         if (m_bInitialized)
  2329.                 Reset(IAISystem::RESET_INTERNAL_LOAD);
  2330.  
  2331.         FlushAllAreas();
  2332.  
  2333.         if (loadDataFlags & eAILoadDataFlag_DesignedAreas)
  2334.         {
  2335.                 m_pNavigation->LoadNavigationData(szLevel, szMission);
  2336.         }
  2337.  
  2338.         if (loadDataFlags & eAILoadDataFlag_MNM)
  2339.         {
  2340.                 if ((loadDataFlags & eAILoadDataFlag_QuickLoad) == 0)
  2341.                 {
  2342.                         LoadMNM(szLevel, szMission, (loadDataFlags & eAILoadDataFlag_AfterExport) != 0);
  2343.                 }
  2344.                 else
  2345.                 {
  2346.                         // TODO: We will need to restore navmesh to desired (initial or saved) state in the case there are some dynamic changes to navmesh
  2347.                 }
  2348.         }
  2349.  
  2350.         m_pSmartObjectManager->SoftReset(); // Re-register smart objects
  2351. }
  2352.  
  2353. void CAISystem::LoadMNM(const char* szLevel, const char* szMission, bool bAfterExporting)
  2354. {
  2355.         //////////////////////////////////////////////////////////////////////////
  2356.         /// MNM
  2357.         /// First clear any previous data, and then load stored meshes
  2358.         /// Note smart objects must go after, they will link to the mesh after is loaded
  2359.         gAIEnv.pNavigationSystem->Clear();
  2360.         ISegmentsManager* pSegmentsManager = gEnv->p3DEngine->GetSegmentsManager();
  2361.         if (gEnv->IsEditor() || !pSegmentsManager)
  2362.         {
  2363.                 char mnmFileName[1024] = { 0 };
  2364.                 cry_sprintf(mnmFileName, "%s/mnmnav%s.bai", szLevel, szMission);
  2365.                 gAIEnv.pNavigationSystem->ReadFromFile(mnmFileName, bAfterExporting);
  2366.         }
  2367. #ifdef DEDICATED_SERVER
  2368.         else
  2369.         {
  2370.                 // load ai data from segment pak instead
  2371.                 pSegmentsManager->ForceLoadSegments(ISegmentsManager::slfNavigation);
  2372.         }
  2373. #endif
  2374. }
  2375.  
  2376. void CAISystem::LoadCover(const char* szLevel, const char* szMission)
  2377. {
  2378.         MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Navigation, 0, "Cover system");
  2379.         LOADING_TIME_PROFILE_SECTION(GetISystem());
  2380.         gAIEnv.pCoverSystem->Clear();
  2381.  
  2382.         char coverFileName[1024] = { 0 };
  2383.         cry_sprintf(coverFileName, "%s/cover%s.bai", szLevel, szMission);
  2384.         gAIEnv.pCoverSystem->ReadSurfacesFromFile(coverFileName);
  2385. }
  2386.  
  2387. void CAISystem::LoadLevelData(const char* szLevel, const char* szMission, const EAILoadDataFlags loadDataFlags /*= eAILoadDataFlag_AllSystems*/)
  2388. {
  2389.         LOADING_TIME_PROFILE_SECTION;
  2390.  
  2391.         CRY_ASSERT(szLevel);
  2392.         CRY_ASSERT_TRACE(szMission && szMission[0],
  2393.                          ("Loading AI data for level %s without a mission: AI navigation will be broken!",
  2394.                           szLevel ? szLevel : "<None>"));
  2395.  
  2396.         if (gEnv->bMultiplayer)
  2397.         {
  2398.                 if (!IsEnabled())
  2399.                         return;
  2400.  
  2401.                 ICVar* pEnableAI = gEnv->pConsole->GetCVar("sv_AISystem");
  2402.                 if (pEnableAI && !pEnableAI->GetIVal())
  2403.                 {
  2404.                         return;
  2405.                 }
  2406.         }
  2407.  
  2408.         SetLevelPath(szLevel);
  2409.  
  2410.         if (loadDataFlags & eAILoadDataFlag_Navigation)
  2411.         {
  2412.                 LoadNavigationData(szLevel, szMission, loadDataFlags);
  2413.         }
  2414.         if (loadDataFlags & eAILoadDataFlag_Covers)
  2415.         {
  2416.                 LoadCover(szLevel, szMission);
  2417.         }
  2418. }
  2419.  
  2420. //====================================================================
  2421. // OnMissionLoaded
  2422. //====================================================================
  2423. void CAISystem::OnMissionLoaded()
  2424. {
  2425.         m_pNavigation->OnMissionLoaded();
  2426. }
  2427.  
  2428. //
  2429. //-----------------------------------------------------------------------------------------------------------
  2430. void CAISystem::ReleaseFormation(CWeakRef<CAIObject> refOwner, bool bDelete)
  2431. {
  2432.         CCCPOINT(CAISystem_ReleaseFormation);
  2433.  
  2434.         FormationMap::iterator fi;
  2435.         fi = m_mapActiveFormations.find(refOwner);
  2436.         if (fi != m_mapActiveFormations.end())
  2437.         {
  2438.                 CFormation* pFormation = fi->second;
  2439.                 if (bDelete && pFormation)
  2440.                 {
  2441.                         //pFormation->ReleasePoints();
  2442.                         delete pFormation;
  2443.                 }
  2444.                 m_mapActiveFormations.erase(fi);
  2445.         }
  2446. }
  2447.  
  2448. //
  2449. //-----------------------------------------------------------------------------------------------------------
  2450. void CAISystem::FreeFormationPoint(CWeakRef<CAIObject> refOwner)
  2451. {
  2452.         FormationMap::iterator fi;
  2453.         fi = m_mapActiveFormations.find(refOwner);
  2454.         if (fi != m_mapActiveFormations.end())
  2455.                 (fi->second)->FreeFormationPoint(refOwner);
  2456. }
  2457.  
  2458. //
  2459. //-----------------------------------------------------------------------------------------------------------
  2460. void CAISystem::FlushSystem(bool bDeleteAll)
  2461. {
  2462.         if (!IsEnabled())
  2463.         {
  2464.                 return;
  2465.         }
  2466.  
  2467.         AILogEvent("CAISystem::FlushSystem");
  2468.         FlushSystemNavigation(bDeleteAll);
  2469.         // remove all the leaders first;
  2470.         gAIEnv.pAIObjectManager->m_Objects.erase(AIOBJECT_LEADER);
  2471.         ;
  2472.         m_lightManager.Reset();
  2473.  
  2474.         if (m_pSmartObjectManager)
  2475.                 m_pSmartObjectManager->ResetBannedSOs();
  2476.  
  2477.         m_dynHideObjectManager.Reset();
  2478.  
  2479.         m_mapFaction.clear();
  2480.         m_mapGroups.clear();
  2481.         m_mapBeacons.clear();
  2482.  
  2483.         FormationMap::iterator iFormation = m_mapActiveFormations.begin(), iEnd = m_mapActiveFormations.end();
  2484.         for (; iFormation != iEnd; ++iFormation)
  2485.                 delete iFormation->second;
  2486.         m_mapActiveFormations.clear();
  2487.  
  2488.         if (gAIEnv.pVisionMap)
  2489.                 gAIEnv.pVisionMap->Reset();
  2490.  
  2491.         if (gAIEnv.pGroupManager)
  2492.                 gAIEnv.pGroupManager->Reset(AIOBJRESET_SHUTDOWN);
  2493.  
  2494.         GetCentralInterestManager()->Reset();
  2495.  
  2496.         if (gAIEnv.pCommunicationManager)
  2497.                 gAIEnv.pCommunicationManager->Reset();
  2498.  
  2499.         if (gAIEnv.pCoverSystem)
  2500.                 gAIEnv.pCoverSystem->Clear();
  2501.  
  2502.         if (gAIEnv.pRayCaster)
  2503.                 gAIEnv.pRayCaster->Reset();
  2504.  
  2505.         if (gAIEnv.pIntersectionTester)
  2506.                 gAIEnv.pIntersectionTester->Reset();
  2507.  
  2508.         if (gAIEnv.pMovementSystem)
  2509.                 gAIEnv.pMovementSystem->Reset();
  2510.  
  2511.         if (gAIEnv.pTacticalPointSystem)
  2512.                 gAIEnv.pTacticalPointSystem->Reset();
  2513.  
  2514.         if (gAIEnv.pSequenceManager)
  2515.                 gAIEnv.pSequenceManager->Reset();
  2516.  
  2517.         if (gAIEnv.pClusterDetector)
  2518.                 gAIEnv.pClusterDetector->Reset();
  2519.  
  2520. #ifdef CRYAISYSTEM_DEBUG
  2521.         if (gAIEnv.pBubblesSystem)
  2522.                 gAIEnv.pBubblesSystem->Reset();
  2523. #endif
  2524.  
  2525.         // Remove all the objects themselves
  2526.         gAIEnv.pAIObjectManager->Reset();
  2527.  
  2528.         // (MATT) Flush all the objects that may have been deregistered on leaving a previous level
  2529.         // Really, this should delete all AI objects regardless {2009/03/27}
  2530.         gAIEnv.pObjectContainer->ReleaseDeregisteredObjects(true);
  2531.         gAIEnv.pObjectContainer->Reset();
  2532.  
  2533.         AIAssert(m_enabledAIActorsSet.empty());
  2534.         AIAssert(m_disabledAIActorsSet.empty());
  2535.         ResetAIActorSets(true);
  2536.  
  2537.         stl::free_container(m_mapGenericShapes);
  2538.  
  2539.         gAIEnv.pBehaviorTreeManager->Reset();
  2540.         gAIEnv.pGraftManager->Reset();
  2541. }
  2542.  
  2543. void CAISystem::LayerEnabled(const char* layerName, bool enabled, bool serialized)
  2544. {
  2545.         if (enabled)
  2546.         {
  2547.                 if (m_pNavigation)
  2548.                         m_pNavigation->BumpDynamicLinkConnectionUpdateTime(gAIEnv.CVars.LayerSwitchDynamicLinkBump, gAIEnv.CVars.LayerSwitchDynamicLinkBumpDuration);
  2549.         }
  2550. }
  2551.  
  2552. //
  2553. //-----------------------------------------------------------------------------------------------------------
  2554. void CAISystem::FlushSystemNavigation(bool bDeleteAll)
  2555. {
  2556.         AILogEvent("CAISystem::FlushSystemNavigation");
  2557.         // clear any paths in the puppets
  2558.         AIObjectOwners::iterator ai;
  2559.         for (ai = gAIEnv.pAIObjectManager->m_Objects.find(AIOBJECT_ACTOR); ai != gAIEnv.pAIObjectManager->m_Objects.end(); ++ai)
  2560.         {
  2561.                 // Strong, so always valid
  2562.                 CPuppet* pPuppet = ai->second.GetAIObject()->CastToCPuppet();
  2563.                 if (ai->first != AIOBJECT_ACTOR)
  2564.                         break;
  2565.                 if (pPuppet)
  2566.                         pPuppet->Reset(AIOBJRESET_INIT);
  2567.         }
  2568.  
  2569.         for (ai = gAIEnv.pAIObjectManager->m_Objects.begin(); ai != gAIEnv.pAIObjectManager->m_Objects.end(); ++ai)
  2570.         {
  2571.                 CAIObject* pObject = ai->second.GetAIObject();
  2572.  
  2573.                 if (pObject)
  2574.                 {
  2575.                         pObject->Reset(AIOBJRESET_INIT);
  2576.                 }
  2577.         }
  2578.  
  2579.         if (m_pNavigation)
  2580.         {
  2581.                 m_pNavigation->FlushSystemNavigation(bDeleteAll);
  2582.         }
  2583. }
  2584.  
  2585. float CAISystem::GetUpdateInterval() const
  2586. {
  2587.         if (gAIEnv.CVars.AIUpdateInterval)
  2588.                 return gAIEnv.CVars.AIUpdateInterval;
  2589.         else
  2590.                 return 0.1f;
  2591. }
  2592.  
  2593. //
  2594. //-----------------------------------------------------------------------------------------------------------
  2595. int CAISystem::GetAITickCount(void)
  2596. {
  2597.         return m_nTickCount;
  2598. }
  2599.  
  2600. //
  2601. //-----------------------------------------------------------------------------------------------------------
  2602. void CAISystem::SendAnonymousSignal(int signalID, const char* text, const Vec3& pos, float radius, IAIObject* pSenderObject, IAISignalExtraData* pData)
  2603. {
  2604.         CCCPOINT(CAISystem_SendAnonymousSignal);
  2605.  
  2606.         IEntity* const pSenderEntity = pSenderObject ? pSenderObject->GetEntity() : NULL;
  2607.  
  2608.         // Go trough all the puppets and vehicles in the surrounding area.
  2609.         // Still makes precise radius check inside because the grid might
  2610.         // return objects in a bigger radius.
  2611.         SEntityProximityQuery query;
  2612.         query.nEntityFlags = ENTITY_FLAG_HAS_AI;
  2613.         query.pEntityClass = NULL;
  2614.         query.box = AABB(Vec3(pos.x - radius, pos.y - radius, pos.z - radius), Vec3(pos.x + radius, pos.y + radius, pos.z + radius));
  2615.         gEnv->pEntitySystem->QueryProximity(query);
  2616.  
  2617.         const float radiusSq = square(radius);
  2618.         for (int i = 0; i < query.nCount; ++i)
  2619.         {
  2620.                 IEntity* const pReceiverEntity = query.pEntities[i];
  2621.                 if (pReceiverEntity)
  2622.                 {
  2623.                         IAIObject* pReceiverAI = pReceiverEntity->GetAI();
  2624.                         if (!pReceiverAI)
  2625.                                 continue;
  2626.  
  2627.                         CPuppet* pReceiverPuppet = pReceiverAI->CastToCPuppet();
  2628.                         if (pReceiverPuppet)
  2629.                         {
  2630.                                 if (pReceiverPuppet->GetParameters().m_PerceptionParams.perceptionScale.visual > 0.01f &&
  2631.                                     pReceiverPuppet->GetParameters().m_PerceptionParams.perceptionScale.audio > 0.01f &&
  2632.                                     Distance::Point_PointSq(pReceiverPuppet->GetPos(), pos) < radiusSq)
  2633.                                 {
  2634.                                         pReceiverPuppet->SetSignal(signalID, text, pSenderEntity, (pData ? new AISignalExtraData(*(AISignalExtraData*)pData) : NULL));
  2635.                                 }
  2636.                         }
  2637.                 }
  2638.         }
  2639.  
  2640.         // Finally delete pData since all recipients have their own copies
  2641.         if (pData)
  2642.         {
  2643.                 delete (AISignalExtraData*)pData;
  2644.         }
  2645. }
  2646.  
  2647. void CAISystem::OnSystemEvent(ESystemEvent event, UINT_PTR wparam, UINT_PTR lparam)
  2648. {
  2649.         switch (event)
  2650.         {
  2651.         case ESYSTEM_EVENT_SW_SHIFT_WORLD:
  2652.                 // offset all AI areas when segmented world shifts.
  2653.                 OffsetAllAreas(*(const Vec3*)wparam);
  2654.                 break;
  2655.         }
  2656. }
  2657.  
  2658. //
  2659. //-----------------------------------------------------------------------------------------------------------
  2660. void CAISystem::ReleaseFormationPoint(CAIObject* pReserved)
  2661. {
  2662.         if (m_mapActiveFormations.empty())
  2663.                 return;
  2664.  
  2665.         CCCPOINT(CAISystem_ReleaseFormationPoint);
  2666.  
  2667.         CWeakRef<CAIObject> refReserved = GetWeakRef(pReserved);
  2668.  
  2669.         FormationMap::iterator fi;
  2670.         CAIActor* pActor = pReserved->CastToCAIActor();
  2671.         CLeader* pLeader = GetLeader(pActor);
  2672.         if (pLeader)
  2673.                 pLeader->FreeFormationPoint(refReserved);
  2674.         else
  2675.                 for (fi = m_mapActiveFormations.begin(); fi != m_mapActiveFormations.end(); ++fi)
  2676.                         (fi->second)->FreeFormationPoint(refReserved);
  2677. }
  2678.  
  2679. //
  2680. //-----------------------------------------------------------------------------------------------------------
  2681. void CAISystem::Update(CTimeValue frameStartTime, float frameDeltaTime)
  2682. {
  2683.         CRY_PROFILE_REGION(PROFILE_AI, "AI System: Update");
  2684.         CRYPROFILE_SCOPE_PROFILE_MARKER("AI System: Update");
  2685.         AISYSTEM_LIGHT_PROFILER();
  2686.  
  2687.         static CTimeValue lastFrameStartTime;
  2688.         if (frameStartTime == lastFrameStartTime)
  2689.                 return;
  2690.  
  2691.         lastFrameStartTime = frameStartTime;
  2692.  
  2693.         if (!m_bInitialized || !IsEnabled())
  2694.                 return;
  2695.  
  2696.         if (!gAIEnv.CVars.AiSystem)
  2697.                 return;
  2698.  
  2699.         CCCPOINT(CAISystem_Update);
  2700.  
  2701.         //      for (AIGroupMap::iterator it = m_mapAIGroups.begin(); it != m_mapAIGroups.end(); ++it)
  2702.         //              it->second->Validate();
  2703.  
  2704.         {
  2705.                 FRAME_PROFILER("AIUpdate - 1", gEnv->pSystem, PROFILE_AI)
  2706.  
  2707.                 if (m_pSmartObjectManager && !m_pSmartObjectManager->IsInitialized())
  2708.                         InitSmartObjects();
  2709.  
  2710.                 if (m_pAIActionManager)
  2711.                         m_pAIActionManager->Update();
  2712.