BVB Source Codes

CRYENGINE Show CommunicationManager.cpp Source code

Return Download CRYENGINE: download CommunicationManager.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #include "StdAfx.h"
  4. #include "CommunicationManager.h"
  5. #include "CommunicationPlayer.h"
  6.  
  7. #include <CryGame/IGame.h>
  8. #include <CryGame/IGameFramework.h>
  9. #include <CryString/StringUtils.h>
  10. #include <CryEntitySystem/IEntitySystem.h>
  11.  
  12. #include "DebugDrawContext.h"
  13.  
  14. const char* CCommunicationManager::m_kTargetIsAbove_VariableName = "TargetIsAbove";
  15. const char* CCommunicationManager::m_kTargetIsBelow_VariableName = "TargetIsBelow";
  16.  
  17. CCommunicationManager::CCommunicationManager(const char* configurationFileName /* = NULL */)
  18.         : m_rootFolder("")
  19.         , m_configurationFileName(configurationFileName)
  20.         , m_playGenID(0)
  21.         , m_globalListeners(10)
  22. {
  23.         m_randomPool.reserve(MaxVariationCount);
  24. }
  25.  
  26. uint32 CCommunicationManager::GetConfigCount() const
  27. {
  28.         return m_configs.size();
  29. }
  30.  
  31. const char* CCommunicationManager::GetConfigName(uint32 index) const
  32. {
  33.         assert(index < m_configs.size());
  34.  
  35.         Configs::const_iterator it = m_configs.begin();
  36.         std::advance(it, (int)index);
  37.  
  38.         return it->second.name.c_str();
  39. }
  40.  
  41. CommConfigID CCommunicationManager::GetConfigIDByIndex(uint32 index) const
  42. {
  43.         assert(index < m_configs.size());
  44.  
  45.         Configs::const_iterator it = m_configs.begin();
  46.         std::advance(it, (int)index);
  47.  
  48.         return it->first;
  49. }
  50.  
  51. void CCommunicationManager::LoadConfigurationAndScanRootFolder(const char* rootFolder)
  52. {
  53.         Reset();
  54.  
  55.         if (!m_configurationFileName.empty())
  56.                 LoadCommunicationSettingsXML(m_configurationFileName);
  57.  
  58.         m_rootFolder = rootFolder;
  59.         ScanFolder(m_rootFolder);
  60. }
  61.  
  62. void CCommunicationManager::ScanFolder(const char* folderName)
  63. {
  64.         string folder(PathUtil::MakeGamePath(string(folderName)));
  65.         folder += "/";
  66.  
  67.         string searchString(folder + "*.xml");
  68.  
  69.         _finddata_t fd;
  70.         intptr_t handle = 0;
  71.  
  72.         ICryPak* pPak = gEnv->pCryPak;
  73.         handle = pPak->FindFirst(searchString.c_str(), &fd);
  74.  
  75.         if (handle > -1)
  76.         {
  77.                 do
  78.                 {
  79.                         if (!strcmp(fd.name, ".") || !strcmp(fd.name, ".."))
  80.                                 continue;
  81.  
  82.                         string completeFilePathAndName(folder + fd.name);
  83.                         if (!m_configurationFileName.compareNoCase(completeFilePathAndName))
  84.                                 continue;
  85.  
  86.                         if (fd.attrib & _A_SUBDIR)
  87.                                 ScanFolder(completeFilePathAndName.c_str());
  88.                         else
  89.                                 LoadCommunicationSettingsXML(completeFilePathAndName.c_str());
  90.  
  91.                 }
  92.                 while (pPak->FindNext(handle, &fd) >= 0);
  93.  
  94.                 pPak->FindClose(handle);
  95.         }
  96. }
  97.  
  98. void CCommunicationManager::LoadVariables(const XmlNodeRef& rootNode, const char* fileName)
  99. {
  100.         if (m_variablesDeclaration.LoadFromXML(rootNode, fileName))
  101.         {
  102.                 m_variables = m_variablesDeclaration.GetDefaults();
  103.                 m_variables.ResetChanged(true);
  104.         }
  105. }
  106.  
  107. void CCommunicationManager::LoadGlobalConfiguration(const XmlNodeRef& rootNode)
  108. {
  109.         if (!rootNode)
  110.                 return;
  111.  
  112.         const char* tagName = rootNode->getTag();
  113.  
  114.         if (!stricmp(tagName, "GlobalConfiguration"))
  115.         {
  116.                 int childCount = rootNode->getChildCount();
  117.  
  118.                 for (int i = 0; i < childCount; ++i)
  119.                 {
  120.                         XmlNodeRef childNode = rootNode->getChild(i);
  121.  
  122.                         if (!stricmp(childNode->getTag(), "WWISE"))
  123.                         {
  124.                                 const char* prefixForPlayTriggerAttribute = "prefixForPlayTrigger";
  125.                                 if (childNode->haveAttr(prefixForPlayTriggerAttribute))
  126.                                 {
  127.                                         m_wiseConfiguration.prefixForPlayTrigger = childNode->getAttr(prefixForPlayTriggerAttribute);
  128.                                 }
  129.  
  130.                                 const char* prefixForStopTriggerAttribute = "prefixForStopTrigger";
  131.                                 if (childNode->haveAttr(prefixForStopTriggerAttribute))
  132.                                 {
  133.                                         m_wiseConfiguration.prefixForStopTrigger = childNode->getAttr(prefixForStopTriggerAttribute);
  134.                                 }
  135.  
  136.                                 const char* switchNameForCharacterVoiceAttribute = "switchNameForCharacterVoice";
  137.                                 if (childNode->haveAttr(switchNameForCharacterVoiceAttribute))
  138.                                 {
  139.                                         m_wiseConfiguration.switchNameForCharacterVoice = childNode->getAttr(switchNameForCharacterVoiceAttribute);
  140.                                 }
  141.  
  142.                                 const char* switchNameForCharacterTypeAttribute = "switchNameForCharacterType";
  143.                                 if (childNode->haveAttr(switchNameForCharacterTypeAttribute))
  144.                                 {
  145.                                         m_wiseConfiguration.switchNameForCharacterType = childNode->getAttr(switchNameForCharacterTypeAttribute);
  146.                                 }
  147.                         }
  148.                 }
  149.         }
  150. }
  151.  
  152. bool CCommunicationManager::LoadCommunicationSettingsXML(const char* fileName)
  153. {
  154.         XmlNodeRef rootNode = GetISystem()->LoadXmlFromFile(fileName);
  155.         if (!rootNode)
  156.         {
  157.                 AIWarning("Failed to open XML file '%s'...", fileName);
  158.  
  159.                 return false;
  160.         }
  161.  
  162.         const char* tagName = rootNode->getTag();
  163.  
  164.         if (!stricmp(tagName, "Communications"))
  165.         {
  166.                 int childCount = rootNode->getChildCount();
  167.  
  168.                 for (int i = 0; i < childCount; ++i)
  169.                 {
  170.                         XmlNodeRef childNode = rootNode->getChild(i);
  171.  
  172.                         if (!stricmp(childNode->getTag(), "GlobalConfiguration"))
  173.                         {
  174.                                 LoadGlobalConfiguration(childNode);
  175.                         }
  176.                         else if (!stricmp(childNode->getTag(), "Variables"))
  177.                         {
  178.                                 LoadVariables(childNode, fileName);
  179.                         }
  180.                         else if (!stricmp(childNode->getTag(), "ChannelConfig"))
  181.                         {
  182.                                 int channelCount = childNode->getChildCount();
  183.  
  184.                                 for (int c = 0; c < channelCount; ++c)
  185.                                 {
  186.                                         XmlNodeRef channelNode = childNode->getChild(c);
  187.                                         if (!m_channels.LoadChannel(channelNode, CommChannelID(0)))
  188.                                                 return false;
  189.                                 }
  190.                         }
  191.                         else if (!stricmp(childNode->getTag(), "Config"))
  192.                         {
  193.                                 if (!childNode->haveAttr("name"))
  194.                                 {
  195.                                         AIWarning("Missing 'name' attribute for 'Config' tag at line %d...",
  196.                                                   childNode->getLine());
  197.  
  198.                                         return false;
  199.                                 }
  200.  
  201.                                 const char* name;
  202.                                 childNode->getAttr("name", &name);
  203.  
  204.                                 std::pair<Configs::iterator, bool> ConfigResult = m_configs.insert(
  205.                                   Configs::value_type(GetConfigID(name), CommunicationsConfig()));
  206.  
  207.                                 if (!ConfigResult.second)
  208.                                 {
  209.                                         if (ConfigResult.first->second.name == name)
  210.                                                 AIWarning("Config '%s' redefinition at line %d...", name, childNode->getLine());
  211.                                         else
  212.                                                 AIWarning("Config name '%s' hash collision!", name);
  213.  
  214.                                         return false;
  215.                                 }
  216.  
  217.                                 CommunicationsConfig& config = ConfigResult.first->second;
  218.                                 config.name = name;
  219.  
  220.                                 int commCount = childNode->getChildCount();
  221.  
  222.                                 for (int c = 0; c < commCount; ++c)
  223.                                 {
  224.                                         XmlNodeRef commNode = childNode->getChild(c);
  225.  
  226.                                         if (!stricmp(commNode->getTag(), "Communication"))
  227.                                         {
  228.                                                 SCommunication comm;
  229.                                                 if (!LoadCommunication(commNode, comm))
  230.                                                         return false;
  231.  
  232.                                                 std::pair<Communications::iterator, bool> iresult = config.comms.insert(
  233.                                                   Communications::value_type(GetCommunicationID(comm.name.c_str()), comm));
  234.  
  235.                                                 if (!iresult.second)
  236.                                                 {
  237.                                                         if (iresult.first->second.name == comm.name)
  238.                                                                 AIWarning("Communication '%s' redefinition at line %d while parsing Communication XML '%s'...",
  239.                                                                           name, commNode->getLine(), fileName);
  240.                                                         else
  241.                                                                 AIWarning("Communication name '%s' hash collision! (existing name=%s)", comm.name.c_str(), iresult.first->second.name.c_str());
  242.  
  243.                                                         return false;
  244.                                                 }
  245.                                         }
  246.                                         else
  247.                                         {
  248.                                                 AIWarning(
  249.                                                   "Unexpected tag '%s' found at line %d while parsing Communication XML '%s'...",
  250.                                                   commNode->getTag(), commNode->getLine(), fileName);
  251.                                         }
  252.                                 }
  253.                         }
  254.                 }
  255.  
  256.                 return true;
  257.         }
  258.         else
  259.         {
  260.                 AIWarning(
  261.                   "Unexpected tag '%s' found at line %d while parsing Communication XML '%s'...",
  262.                   rootNode->getTag(), rootNode->getLine(), fileName);
  263.         }
  264.  
  265.         return false;
  266. }
  267.  
  268. bool FlagAttr(const XmlNodeRef& node, const char* attribute, uint32& flags, uint32 flag)
  269. {
  270.         XMLUtils::BoolType flagValue = XMLUtils::GetBoolType(node, attribute, (flags & flag) ? XMLUtils::True : XMLUtils::False);
  271.  
  272.         if (flagValue == XMLUtils::Invalid)
  273.         {
  274.                 AIWarning("Invalid value for attribute '%s' tag '%s' at line %d...",
  275.                           attribute, node->getTag(), node->getLine());
  276.  
  277.                 return false;
  278.         }
  279.  
  280.         flags &= ~flag;
  281.         if (flagValue == XMLUtils::True)
  282.                 flags |= flag;
  283.  
  284.         return true;
  285. }
  286.  
  287. bool FinishMethod(const XmlNodeRef& node, const char* attribute, uint32& flags)
  288. {
  289.         if (node->haveAttr(attribute))
  290.         {
  291.                 const char* finishMethod;
  292.                 node->getAttr(attribute, &finishMethod);
  293.  
  294.                 flags &= ~SCommunication::FinishAll;
  295.  
  296.                 stack_string methodList(finishMethod);
  297.                 methodList.MakeLower();
  298.  
  299.                 int start = 0;
  300.                 stack_string method = methodList.Tokenize(",", start);
  301.  
  302.                 while (!method.empty())
  303.                 {
  304.                         method.Trim();
  305.  
  306.                         if (method == "animation")
  307.                                 flags |= SCommunication::FinishAnimation;
  308.                         else if (method == "sound")
  309.                                 flags |= SCommunication::FinishSound;
  310.                         else if (method == "voice")
  311.                                 flags |= SCommunication::FinishVoice;
  312.                         else if (method == "timeout")
  313.                                 flags |= SCommunication::FinishTimeout;
  314.                         else if (method == "all")
  315.                                 flags |= SCommunication::FinishAll;
  316.                         else
  317.                         {
  318.                                 AIWarning("Invalid value '%s' for attribute '%s' tag '%s' at line %d...",
  319.                                           method.c_str(), attribute, node->getTag(), node->getLine());
  320.  
  321.                                 return false;
  322.                         }
  323.  
  324.                         method = methodList.Tokenize(",", start);
  325.                 }
  326.         }
  327.  
  328.         return true;
  329. }
  330.  
  331. bool Blocking(const XmlNodeRef& node, const char* attribute, uint32& flags)
  332. {
  333.         if (node->haveAttr(attribute))
  334.         {
  335.                 const char* blocking;
  336.                 node->getAttr(attribute, &blocking);
  337.  
  338.                 flags &= ~SCommunication::BlockAll;
  339.  
  340.                 stack_string methodList(blocking);
  341.                 methodList.MakeLower();
  342.  
  343.                 int start = 0;
  344.                 stack_string method = methodList.Tokenize(",", start);
  345.  
  346.                 while (!method.empty())
  347.                 {
  348.                         method.Trim();
  349.  
  350.                         if (method == "movement")
  351.                                 flags |= SCommunication::BlockMovement;
  352.                         else if (method == "fire")
  353.                                 flags |= SCommunication::BlockFire;
  354.                         else if (method == "all")
  355.                                 flags |= SCommunication::BlockAll;
  356.                         else if (method == "none")
  357.                         {
  358.                                 flags &= ~SCommunication::BlockAll;
  359.                         }
  360.                         else
  361.                         {
  362.                                 AIWarning("Invalid value '%s' for attribute '%s' tag '%s' at line %d...",
  363.                                           method.c_str(), attribute, node->getTag(), node->getLine());
  364.  
  365.                                 return false;
  366.                         }
  367.  
  368.                         method = methodList.Tokenize(",", start);
  369.                 }
  370.         }
  371.  
  372.         return true;
  373. }
  374.  
  375. bool ChoiceMethod(const XmlNodeRef& node, const char* attribute, SCommunication::EVariationChoiceMethod& method)
  376. {
  377.         const char* choiceMethod;
  378.  
  379.         if (node->haveAttr(attribute))
  380.         {
  381.                 node->getAttr(attribute, &choiceMethod);
  382.  
  383.                 if (!stricmp(choiceMethod, "random"))
  384.                         method = SCommunication::Random;
  385.                 else if (!stricmp(choiceMethod, "sequence"))
  386.                         method = SCommunication::Sequence;
  387.                 else if (!stricmp(choiceMethod, "randomsequence"))
  388.                         method = SCommunication::RandomSequence;
  389.                 else if (!stricmp(choiceMethod, "match"))
  390.                         method = SCommunication::Match;
  391.                 else
  392.                 {
  393.                         AIWarning("Invalid value for attribute '%s' tag '%s' at line %d...",
  394.                                   attribute, node->getTag(), node->getLine());
  395.  
  396.                         return false;
  397.                 }
  398.         }
  399.         return true;
  400. }
  401.  
  402. bool AnimationType(const XmlNodeRef& node, const char* attribute, uint32& flags)
  403. {
  404.         if (node->haveAttr(attribute))
  405.         {
  406.                 const char* animationType;
  407.                 node->getAttr(attribute, &animationType);
  408.  
  409.                 flags &= ~SCommunication::AnimationAction;
  410.  
  411.                 if (!stricmp(animationType, "action"))
  412.                         flags |= SCommunication::AnimationAction;
  413.                 else if (stricmp(animationType, "signal"))
  414.                 {
  415.                         AIWarning("Invalid value for attribute '%s' tag '%s' at line %d...",
  416.                                   attribute, node->getTag(), node->getLine());
  417.  
  418.                         return false;
  419.                 }
  420.         }
  421.  
  422.         return true;
  423. }
  424.  
  425. bool CCommunicationManager::LoadCommunication(const XmlNodeRef& commNode, SCommunication& comm)
  426. {
  427.         if (!commNode->haveAttr("name"))
  428.         {
  429.                 AIWarning("Missing 'name' attribute for 'Communication' tag at line %d...",
  430.                           commNode->getLine());
  431.  
  432.                 return false;
  433.         }
  434.  
  435.         const char* name = 0;
  436.         commNode->getAttr("name", &name);
  437.  
  438.         comm.name = name;
  439.         comm.choiceMethod = SCommunication::RandomSequence;
  440.         comm.responseChoiceMethod = SCommunication::RandomSequence;
  441.  
  442.         if (!ChoiceMethod(commNode, "choiceMethod", comm.choiceMethod))
  443.                 return false;
  444.  
  445.         if (commNode->haveAttr("responseName"))
  446.         {
  447.                 const char* responseName;
  448.                 commNode->getAttr("responseName", &responseName);
  449.                 comm.responseID = GetCommunicationID(responseName);
  450.         }
  451.         else
  452.         {
  453.                 comm.responseID = CommID(0);
  454.         }
  455.  
  456.         if (!ChoiceMethod(commNode, "responseChoiceMethod", comm.responseChoiceMethod))
  457.                 return false;
  458.  
  459.         SCommunicationVariation deflt;
  460.         deflt.flags = SCommunication::FinishAll;
  461.  
  462.         if (!LoadVariation(commNode, deflt))
  463.                 return false;
  464.  
  465.         int variationCount = commNode->getChildCount();
  466.  
  467.         comm.hasAnimation = false;
  468.         comm.forceAnimation = false;
  469.  
  470.         commNode->getAttr("forceAnimation", comm.forceAnimation);
  471.  
  472.         for (int i = 0; i < variationCount; ++i)
  473.         {
  474.                 XmlNodeRef varNode = commNode->getChild(i);
  475.  
  476.                 if (stricmp(varNode->getTag(), "Variation"))
  477.                 {
  478.                         AIWarning("Unexpected tag '%s' found at line %d...", varNode->getTag(), varNode->getLine());
  479.  
  480.                         return false;
  481.                 }
  482.  
  483.                 SCommunicationVariation variation(deflt);
  484.                 if (!LoadVariation(varNode, variation))
  485.                         return false;
  486.  
  487.                 if (!variation.animationName.empty())
  488.                         comm.hasAnimation = true;
  489.  
  490.                 comm.variations.push_back(variation);
  491.  
  492.                 if (comm.variations.size() == MaxVariationCount)
  493.                 {
  494.                         if (variationCount > MaxVariationCount)
  495.                         {
  496.                                 AIWarning("Maximum number of variations reached for '%s' found at line %d...", commNode->getTag(),
  497.                                           commNode->getLine());
  498.                         }
  499.  
  500.                         break;
  501.                 }
  502.         }
  503.  
  504.         return true;
  505. }
  506.  
  507. bool CCommunicationManager::LoadVariation(const XmlNodeRef& varNode, SCommunicationVariation& variation)
  508. {
  509.         if (varNode->haveAttr("animationName"))
  510.         {
  511.                 const char* animationName;
  512.                 varNode->getAttr("animationName", &animationName);
  513.                 variation.animationName = animationName;
  514.         }
  515.  
  516.         if (varNode->haveAttr("soundName"))
  517.         {
  518.                 const char* soundName;
  519.                 varNode->getAttr("soundName", &soundName);
  520.                 variation.soundName = soundName;
  521.         }
  522.  
  523.         if (varNode->haveAttr("voiceName"))
  524.         {
  525.                 const char* voiceName;
  526.                 varNode->getAttr("voiceName", &voiceName);
  527.                 variation.voiceName = voiceName;
  528.         }
  529.  
  530.         if (!FlagAttr(varNode, "lookAtTarget", variation.flags, SCommunication::LookAtTarget))
  531.                 return false;
  532.  
  533.         if (!FinishMethod(varNode, "finishMethod", variation.flags))
  534.                 return false;
  535.  
  536.         if (!Blocking(varNode, "blocking", variation.flags))
  537.                 return false;
  538.  
  539.         if (!AnimationType(varNode, "animationType", variation.flags))
  540.                 return false;
  541.  
  542.         if (varNode->haveAttr("timeout"))
  543.         {
  544.                 float timeout = 0.0f;
  545.                 if (varNode->getAttr("timeout", timeout))
  546.                         variation.timeout = timeout;
  547.         }
  548.  
  549.         if (varNode->haveAttr("condition"))
  550.         {
  551.                 stack_string condition = varNode->getAttr("condition");
  552.                 if (condition.empty())
  553.                         return false;
  554.  
  555.                 variation.condition.reset(new Variables::Expression(condition, m_variablesDeclaration));
  556.         }
  557.  
  558.         return true;
  559. }
  560.  
  561. void CCommunicationManager::Reload()
  562. {
  563.         Reset();
  564.         m_testManager.Reset();
  565.  
  566.         m_configs.clear();
  567.  
  568.         m_channels.Clear();
  569.         m_player.Clear();
  570.  
  571.         if (!m_configurationFileName.empty())
  572.                 LoadCommunicationSettingsXML(m_configurationFileName);
  573.  
  574.         ScanFolder(m_rootFolder);
  575. }
  576.  
  577. void CCommunicationManager::Reset()
  578. {
  579.         m_variablesDeclaration = Variables::Declarations();
  580.         {
  581.                 // Use global heap, as SelectionVariables use a deque, which allocates during (re)construction
  582.                 stl::reconstruct(m_variables);
  583.         }
  584.  
  585.         m_channels.Reset();
  586.         m_player.Reset();
  587.  
  588.         ResetHistory();
  589.  
  590.         m_playing.clear();
  591.         m_orderedQueue.clear();
  592.         m_unorderedQueue.clear();
  593.  
  594.         m_restrictedActors.clear();
  595.         m_actorPropertiesMap.clear();
  596.  
  597.         m_debugHistoryMap.clear();
  598.         //Don't clear the stats, so they don't get reset on level load
  599.         //m_debugStatisticsMap.clear();
  600.  
  601.         m_testManager.Reset();
  602.  
  603.         stl::free_container(m_unfinalized);
  604. }
  605.  
  606. void CCommunicationManager::ResetHistory()
  607. {
  608.         Configs::iterator it = m_configs.begin();
  609.         Configs::iterator end = m_configs.end();
  610.  
  611.         for (; it != end; ++it)
  612.         {
  613.                 CommunicationsConfig& config = it->second;
  614.  
  615.                 Communications::iterator cit = config.comms.begin();
  616.                 Communications::iterator cend = config.comms.end();
  617.  
  618.                 for (; cit != cend; ++cit)
  619.                 {
  620.                         SCommunication& comm = cit->second;
  621.                         comm.history = SCommunication::History();
  622.                 }
  623.         }
  624. }
  625.  
  626. void CCommunicationManager::Update(float updateTime)
  627. {
  628.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  629.  
  630.         m_channels.Update(updateTime);
  631.         m_player.Update(updateTime);
  632.         m_testManager.Update(updateTime);
  633.  
  634.         UpdateActorRestrictions(updateTime);
  635.  
  636.         UpdateQueue(m_orderedQueue, updateTime);
  637.         UpdateQueue(m_unorderedQueue, updateTime);
  638.  
  639.         ProcessQueues();
  640.  
  641.         CullPlayingCommunications();
  642.  
  643.         if (gAIEnv.CVars.DebugDrawCommunication > 1 && gAIEnv.CVars.DebugDraw > 0 && gAIEnv.CVars.DebugDrawCommunication != 6)
  644.                 UpdateDebugHistory(updateTime);
  645. }
  646.  
  647. ///Looks for an existing record in the debug history, and either inserts a new record if not found, or updates an existing one
  648. void CCommunicationManager::UpdateDebugHistoryEntry(IEntity* pEntity, const CommDebugEntry& entryToUpdate)
  649. {
  650.         std::vector<CommDebugEntry>& targetValues = m_debugHistoryMap[pEntity->GetId()];
  651.  
  652.         std::vector<CommDebugEntry>::iterator existingEntry = std::find_if(targetValues.begin(), targetValues.end(), FindMatchingRecord(entryToUpdate));
  653.  
  654.         if (existingEntry != targetValues.end())
  655.         {
  656.                 existingEntry->m_type = entryToUpdate.m_type;
  657.  
  658.                 existingEntry->UpdateChannelInfo(entryToUpdate);
  659.  
  660.                 //Reinitialize this entry's display status as its now being rerun
  661.                 existingEntry->m_displayed = false;
  662.         }
  663.         else
  664.                 targetValues.push_back(entryToUpdate);
  665.  
  666. }
  667.  
  668. ///Updates the time displayed of all tracked debug records
  669. void CCommunicationManager::UpdateDebugHistory(float updateTime)
  670. {
  671.         for (TDebugMapHistory::iterator iter(m_debugHistoryMap.begin()); iter != m_debugHistoryMap.end(); ++iter)
  672.         {
  673.                 std::vector<CommDebugEntry>& entityEntries = iter->second;
  674.  
  675.                 ///Update times and display status for existing entries
  676.                 for (std::vector<CommDebugEntry>::iterator entryIt = entityEntries.begin(); entryIt != entityEntries.end(); ++entryIt)
  677.                 {
  678.                         CommDebugEntry& entry = *entryIt;
  679.  
  680.                         entry.m_displayed = (entryIt->m_timeTracked > 2.0f);
  681.                         entry.m_timeTracked += updateTime;
  682.  
  683.                 }
  684.  
  685.                 ///Clear out old records that haven't been played for awhile
  686.                 CommDebugEntry searchEntry;
  687.                 searchEntry.m_timeTracked = 20.0f;
  688.                 entityEntries.erase(std::remove_if(entityEntries.begin(), entityEntries.end(), FindMatchingRecord(searchEntry)), entityEntries.end());
  689.         }
  690.  
  691.         ///Finds empty entity entries in the debug map
  692.         TDebugMapHistory::iterator iter = m_debugHistoryMap.begin();
  693.         TDebugMapHistory::iterator endIter = m_debugHistoryMap.end();
  694.  
  695.         for (; iter != endIter; )
  696.         {
  697.                 if (iter->second.empty())
  698.                         m_debugHistoryMap.erase(iter++);
  699.                 else
  700.                         ++iter;
  701.         }
  702. }
  703.  
  704. void CCommunicationManager::DebugDraw()
  705. {
  706.         typedef std::map<IEntity*, string> TDebugMap;
  707.         TDebugMap debugInfoMap;
  708.         string temp;
  709.  
  710.         // Write playing
  711.         for (PlayingCommunications::const_iterator it(m_playing.begin()); it != m_playing.end(); ++it)
  712.         {
  713.                 CommPlayID playID = it->first;
  714.                 const PlayingCommunication& playingComm = it->second;
  715.  
  716.                 CommID commID = m_player.GetCommunicationID(playID);
  717.                 if (const char* commName = GetCommunicationName(commID))
  718.                 {
  719.                         if (IEntity* pEntity = gEnv->pEntitySystem->GetEntity(playingComm.actorID))
  720.                         {
  721.                                 CommChannelID channelID(0);
  722.  
  723.                                 if (playingComm.channel)
  724.                                         channelID = playingComm.channel->GetID();
  725.  
  726.                                 temp.Format("P: %s: %u\n", commName, channelID.id);
  727.                                 debugInfoMap[pEntity].append(temp);
  728.  
  729.                                 CommDebugEntry newEntry(commName, playID, "Playing", channelID);
  730.                                 UpdateDebugHistoryEntry(pEntity, newEntry);
  731.  
  732.                         }
  733.                         else
  734.                         {
  735.                                 CDebugDrawContext dc;
  736.                                 dc->Draw2dLabel(40.0f, 40.0f, 3.0f, ColorB(255, 128, 0), false, "No entity found for playing comm: %s", commName);
  737.                         }
  738.                 }
  739.                 else
  740.                 {
  741.                         CDebugDrawContext dc;
  742.                         dc->Draw2dLabel(40.0f, 50.0f, 3.0f, ColorB(255, 128, 0), false, "Abandoned communication in playing set: playID[%d] for entityID[%d]", playID.id, playingComm.actorID);
  743.                 }
  744.         }
  745.  
  746.         // Write ordered queued
  747.         for (QueuedCommunications::const_iterator it(m_orderedQueue.begin()); it != m_orderedQueue.end(); ++it)
  748.         {
  749.                 const QueuedCommunication& queuedComm = *it;
  750.  
  751.                 IEntity* pEntity = gEnv->pEntitySystem->GetEntity(queuedComm.request.actorID);
  752.                 const char* commName = GetCommunicationName(queuedComm.request.commID);
  753.  
  754.                 if (pEntity)
  755.                 {
  756.                         temp.Format("Q[%" PRI_PTRDIFF_T "] %s\n", std::distance<QueuedCommunications::const_iterator>(m_orderedQueue.begin(), it), commName);
  757.                         debugInfoMap[pEntity].append(temp);
  758.  
  759.                         CommDebugEntry newEntry(commName, queuedComm.playID, "QueuedOrdered", queuedComm.request.channelID);
  760.                         UpdateDebugHistoryEntry(pEntity, newEntry);
  761.  
  762.                 }
  763.         }
  764.  
  765.         // Write unordered queued
  766.         for (QueuedCommunications::const_iterator it(m_unorderedQueue.begin()); it != m_unorderedQueue.end(); ++it)
  767.         {
  768.                 const QueuedCommunication& queuedComm = *it;
  769.  
  770.                 IEntity* pEntity = gEnv->pEntitySystem->GetEntity(queuedComm.request.actorID);
  771.                 const char* commName = GetCommunicationName(queuedComm.request.commID);
  772.  
  773.                 if (pEntity)
  774.                 {
  775.                         temp.Format("U: %s\n", commName);
  776.                         debugInfoMap[pEntity].append(temp);
  777.  
  778.                         CommDebugEntry newEntry(commName, queuedComm.playID, "QueuedOrdered", queuedComm.request.channelID);
  779.                         UpdateDebugHistoryEntry(pEntity, newEntry);
  780.  
  781.                 }
  782.         }
  783.  
  784.         // Draw the text for all active comms for each entity as a 3d label near their location
  785.         CDebugDrawContext dc;
  786.         for (TDebugMap::const_iterator iter(debugInfoMap.begin()); iter != debugInfoMap.end(); ++iter)
  787.         {
  788.                 IEntity* pEntity = iter->first;
  789.                 string text(iter->second);
  790.  
  791.                 dc->Draw3dLabel(pEntity->GetWorldPos() + Vec3(0, 0, 0.2f), 1.2f, "%s", text.c_str());
  792.         }
  793.  
  794.         // Draw the history of comms for each entity as 2d labels
  795.         if (gAIEnv.CVars.DebugDrawCommunication > 1 && gAIEnv.CVars.DebugDrawCommunication != 6)
  796.         {
  797.                 float offset = 0.0f;
  798.  
  799.                 for (TDebugMapHistory::iterator iter(m_debugHistoryMap.begin()); iter != m_debugHistoryMap.end(); ++iter)
  800.                 {
  801.                         IEntitySystem* pEntitySystem = gEnv->pEntitySystem;
  802.  
  803.                         CRY_ASSERT(pEntitySystem);
  804.  
  805.                         IEntity* pEntity = pEntitySystem->GetEntity(iter->first);
  806.                         std::vector<CommDebugEntry>& entityEntries = iter->second;
  807.  
  808.                         if (!pEntity)
  809.                         {
  810.                                 CryLogAlways("CommunicationManager::DisplayDebugHistory: Entity no longer valid with ID:%i Skipping", iter->first);
  811.                                 continue;
  812.                         }
  813.  
  814.                         dc->Draw2dLabel(40.0f, 80.0f + offset, 2.0f, ColorB(0, 255, 0), false, "Communication History for ENTITY:%s", pEntity->GetName());
  815.                         offset += 22;
  816.  
  817.                         int numberDisplayed = 0;
  818.                         for (std::vector<CommDebugEntry>::reverse_iterator entryIt = entityEntries.rbegin();
  819.                              entryIt != entityEntries.rend() && numberDisplayed < gAIEnv.CVars.DebugDrawCommunicationHistoryDepth;
  820.                              ++entryIt, ++numberDisplayed)
  821.                         {
  822.                                 CommDebugEntry& entry = *entryIt;
  823.                                 ColorB color = ColorB(255, 128, 0);
  824.                                 string status = "Done";
  825.                                 //If this entry is active to the history then give it a different color and use its type
  826.                                 if (!entry.m_displayed)
  827.                                 {
  828.                                         color = ColorB(255, 255, 0);
  829.                                         status = entry.m_type;
  830.                                 }
  831.  
  832.                                 string channels;
  833.  
  834.                                 if (!entry.m_channels.empty())
  835.                                 {
  836.                                         for (std::set<CommChannelID>::iterator channelIt = entry.m_channels.begin(); channelIt != entry.m_channels.end(); ++channelIt)
  837.                                         {
  838.                                                 if (channels != "")
  839.                                                         channels += ",";
  840.  
  841.                                                 const string& channelName = m_channels.GetChannelParams(*channelIt).name;
  842.                                                 if (channelName == "")
  843.                                                         channels += "Unknown";
  844.                                                 else
  845.                                                         channels += channelName;
  846.                                         }
  847.                                 }
  848.  
  849.                                 dc->Draw2dLabel(60.0f, 80.0f + offset, 2.0f, color, false, "Communication: %s Status: %s Channels:%s", entry.m_commName.c_str(), status.c_str(), channels.c_str());
  850.  
  851.                                 offset += 20;
  852.                         }
  853.                 }
  854.         }
  855.  
  856. }
  857.  
  858. CommChannelID CCommunicationManager::GetChannelID(const char* name) const
  859. {
  860.         return m_channels.GetChannelID(name);
  861. }
  862.  
  863. size_t CCommunicationManager::GetPriority(const CommPlayID& playID) const
  864. {
  865.         PlayingCommunications::const_iterator playIt = m_playing.find(playID);
  866.  
  867.         if (playIt != m_playing.end())
  868.         {
  869.                 const PlayingCommunication& playingComm = playIt->second;
  870.  
  871.                 return playingComm.channel->GetPriority();
  872.         }
  873.  
  874.         //Assuming the playID is no longer valid, assume priority 0
  875.         return 0;
  876. }
  877.  
  878. CommConfigID CCommunicationManager::GetConfigID(const char* name) const
  879. {
  880.         return CommConfigID(CryStringUtils::CalculateHashLowerCase(name));
  881. }
  882.  
  883. CommID CCommunicationManager::GetCommunicationID(const char* name) const
  884. {
  885.         return CommID(CCrc32::ComputeLowercase(name));
  886. }
  887.  
  888. const char* CCommunicationManager::GetCommunicationName(const CommID& communicationID) const
  889. {
  890.         Configs::const_iterator cit = m_configs.begin();
  891.         Configs::const_iterator cend = m_configs.end();
  892.  
  893.         for (; cit != cend; ++cit)
  894.         {
  895.                 const CommunicationsConfig& config = cit->second;
  896.  
  897.                 Communications::const_iterator commIt = config.comms.find(communicationID);
  898.                 if (commIt == config.comms.end())
  899.                         continue;
  900.  
  901.                 const SCommunication& comm = commIt->second;
  902.                 return comm.name.c_str();
  903.         }
  904.  
  905.         return 0;
  906. }
  907.  
  908. const char* CCommunicationManager::GetConfigCommunicationNameByIndex(const CommConfigID& configID, uint32 index) const
  909. {
  910.         Configs::const_iterator configIt = m_configs.find(configID);
  911.  
  912.         if (configIt != m_configs.end())
  913.         {
  914.                 const CommunicationsConfig& config = configIt->second;
  915.  
  916.                 assert(index < config.comms.size());
  917.  
  918.                 Communications::const_iterator it = config.comms.begin();
  919.                 std::advance(it, (int)index);
  920.  
  921.                 return it->second.name.c_str();
  922.         }
  923.  
  924.         return 0;
  925. }
  926.  
  927. uint32 CCommunicationManager::GetConfigCommunicationCount(const CommConfigID& configID) const
  928. {
  929.         Configs::const_iterator configIt = m_configs.find(configID);
  930.  
  931.         uint32 communicationCount = 0;
  932.  
  933.         if (configIt != m_configs.end())
  934.         {
  935.                 const CommunicationsConfig& config = configIt->second;
  936.                 communicationCount = config.comms.size();
  937.         }
  938.  
  939.         return communicationCount;
  940. }
  941.  
  942. bool CCommunicationManager::CanCommunicationPlay(const SCommunicationRequest& request, float* estimatedWaitTime)
  943. {
  944.         if (estimatedWaitTime)
  945.                 *estimatedWaitTime = FLT_MAX;
  946.  
  947.         CommunicationChannel::Ptr channel = m_channels.GetChannel(request.channelID, request.actorID);
  948.         if (!channel)
  949.                 return false;
  950.  
  951.         if (channel->IsFree())
  952.         {
  953.                 if (estimatedWaitTime)
  954.                         *estimatedWaitTime = 0.0f;
  955.  
  956.                 return true;
  957.         }
  958.  
  959.         return false;
  960. }
  961.  
  962. bool CCommunicationManager::CanForceAnimation(const SCommunication& comm, const SCommunicationRequest& request)
  963. {
  964.         //If this comm doesn't support animation forcing or the request specified to skip the animation, then return
  965.         if (!comm.forceAnimation || request.skipCommAnimation)
  966.                 return false;
  967.  
  968.         //Assumes active communications of lower priority then queried request have already been flushed out of the system.
  969.  
  970.         //Otherwise check for playing communications to see if any of them have an animation. If so then return false.
  971.         PlayingCommunications::const_iterator playingIt = m_playing.begin();
  972.         PlayingCommunications::const_iterator playingEnd = m_playing.end();
  973.         for (; playingIt != playingEnd; ++playingIt)
  974.         {
  975.                 const PlayingCommunication& playingComm = playingIt->second;
  976.  
  977.                 if (request.actorID == playingComm.actorID && !playingComm.animName.empty())
  978.                         return false;
  979.  
  980.         }
  981.  
  982.         //Also need to check for unfinalized animations.
  983.         CommunicationVec::const_iterator unfinalizedIt = m_unfinalized.begin();
  984.         CommunicationVec::const_iterator unfinalizedEnd = m_unfinalized.end();
  985.         for (; unfinalizedIt != unfinalizedEnd; ++unfinalizedIt)
  986.         {
  987.                 const PlayingCommunication& unfinalizedComm = *unfinalizedIt;
  988.  
  989.                 if (request.actorID == unfinalizedComm.actorID && !unfinalizedComm.animName.empty())
  990.                         return false;
  991.         }
  992.  
  993.         return true;
  994.  
  995. }
  996.  
  997. CommPlayID CCommunicationManager::PlayCommunication(SCommunicationRequest& request)
  998. {
  999.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  1000.  
  1001.         Configs::iterator cit = m_configs.find(request.configID);
  1002.         if (cit == m_configs.end())
  1003.                 return CommPlayID(0);
  1004.  
  1005.         CommunicationsConfig& config = cit->second;
  1006.         Communications::iterator commIt = config.comms.find(request.commID);
  1007.         if (commIt == config.comms.end())
  1008.                 return CommPlayID(0);
  1009.  
  1010.         SCommunication& comm = commIt->second;
  1011.  
  1012.         // If this is an animated communication
  1013.         if (comm.hasAnimation)
  1014.         {
  1015.                 IEntity* pEntity = gEnv->pEntitySystem->GetEntity(request.actorID);
  1016.                 IAIObject* pAIObject = pEntity ? pEntity->GetAI() : 0;
  1017.  
  1018.                 if (IAIActorProxy* aiProxy = pAIObject ? pAIObject->GetProxy() : 0)
  1019.                 {
  1020.                         // Ensure no SO transition is in progress
  1021.                         if (aiProxy->IsPlayingSmartObjectAction())
  1022.                                 return CommPlayID(0);
  1023.                 }
  1024.         }
  1025.  
  1026.         CommunicationChannel::Ptr channel = m_channels.GetChannel(request.channelID, request.actorID);
  1027.  
  1028.         if (channel)
  1029.         {
  1030.                 ++m_playGenID.id;
  1031.                 if (!m_playGenID)
  1032.                         ++m_playGenID.id;
  1033.  
  1034.                 if (gAIEnv.CVars.RecordCommunicationStats > 0)
  1035.                 {
  1036.                         //Record the request here if statistics are being generated
  1037.                         CommDebugCount& commCount = m_debugStatisticsMap[CommKeys(request.configID, request.commID)];
  1038.                         ++commCount.requestCount;
  1039.                 }
  1040.  
  1041.                 FlushCommunications(request, channel);
  1042.  
  1043.                 SActorReadabilitySettings actorSettings;
  1044.                 GetActorData(request.actorID, actorSettings);
  1045.  
  1046.                 //Skip animations for this request if actor ignores them
  1047.                 if (actorSettings.m_bIgnoreAnimations || IsAnimationRestricted(request.actorID))
  1048.                 {
  1049.                         request.skipCommAnimation = true;
  1050.                 }
  1051.                 //Only skip communication sounds for channels that don't ignore actor restrictions.
  1052.                 if ((actorSettings.m_bIgnoreVoice || IsVoiceRestricted(request.actorID)) && !channel->IgnoresActorSilence())
  1053.                 {
  1054.                         request.skipCommSound = true;
  1055.                 }
  1056.  
  1057.                 //If a combination of request settings no longer has a component, then don't bother to try playing/queueing it.
  1058.                 if (request.skipCommAnimation && request.skipCommSound)
  1059.                         return CommPlayID(0);
  1060.  
  1061.                 bool forceAnimations = CanForceAnimation(comm, request);
  1062.  
  1063.                 // Plays communication if the channel is free or forcing animations.
  1064.                 if (forceAnimations || channel->IsFree())
  1065.                 {
  1066.                         //Make sure to always flush the queues of lower priority items
  1067.                         FlushQueue(m_orderedQueue, channel, request.actorID);
  1068.                         FlushQueue(m_unorderedQueue, channel, request.actorID);
  1069.  
  1070.                         //If the channel is not free, but the comm forcibly plays the animation, then request skip sound portion
  1071.                         if (forceAnimations && !channel->IsFree())
  1072.                         {
  1073.                                 request.skipCommSound = true;
  1074.                         }
  1075.  
  1076.                         Play(m_playGenID, request, channel, comm);
  1077.                 }
  1078.                 else
  1079.                 {
  1080.                         //Make sure queue not insert into gets flushed as well
  1081.                         if (request.ordering == SCommunicationRequest::Ordered)
  1082.                         {
  1083.                                 FlushQueue(m_orderedQueue, channel, request.actorID);
  1084.                                 FlushQueue(m_unorderedQueue, channel, request.actorID);
  1085.  
  1086.                                 Queue(m_orderedQueue, m_playGenID, request);
  1087.                         }
  1088.                         else
  1089.                         {
  1090.                                 FlushQueue(m_orderedQueue, channel, request.actorID);
  1091.                                 FlushQueue(m_unorderedQueue, channel, request.actorID);
  1092.  
  1093.                                 Queue(m_unorderedQueue, m_playGenID, request);
  1094.                         }
  1095.                 }
  1096.  
  1097.                 return m_playGenID;
  1098.         }
  1099.  
  1100.         return CommPlayID(0);
  1101. }
  1102.  
  1103. void CCommunicationManager::FlushCommunications(const SCommunicationRequest& request, CommunicationChannel::Ptr channel)
  1104. {
  1105.         //Need to stop every playing communication with a lower priority. Assume ordered, since previous higher entries would clear out ones earlier in the queue
  1106.         PlayingCommunications::iterator pit = m_playing.begin();
  1107.         PlayingCommunications::iterator pend = m_playing.end();
  1108.         while (pit != pend)
  1109.         {
  1110.                 const CommunicationChannel::Ptr targetChannel = pit->second.channel;
  1111.                 if (channel->GetPriority() > targetChannel->GetPriority())
  1112.                 {
  1113.                         bool commRemoved = false;
  1114.                         if (channel->GetType() == SCommunicationChannelParams::Personal)
  1115.                         {
  1116.                                 if (request.actorID == pit->second.actorID)
  1117.                                 {
  1118.                                         commRemoved = true;
  1119.                                 }
  1120.                         }
  1121.                         //For group/global assume it should be replaced
  1122.                         else
  1123.                         {
  1124.                                 commRemoved = true;
  1125.                         }
  1126.  
  1127.                         if (commRemoved)
  1128.                         {
  1129.                                 PlayingCommunications::iterator stopIt = pit++;
  1130.                                 StopCommunication(stopIt->first);
  1131.  
  1132.                                 //If the channel is no longer playing a communication, but still has an imposed silence time, then reset the channel silence to the flush time now
  1133.                                 if (!channel->IsOccupied() && !channel->IsFree())
  1134.                                         channel->ResetSilence();
  1135.  
  1136.                                 continue;
  1137.                         }
  1138.                 }
  1139.  
  1140.                 ++pit;
  1141.         }
  1142.  
  1143.         //Need to stop unfinalized communications with a lower priority. Assume ordered, since previous higher entries would clear out ones earlier in the queue
  1144.         for (size_t commIndex = 0; commIndex < m_unfinalized.size(); )
  1145.         {
  1146.                 PlayingCommunication& comm = m_unfinalized[commIndex];
  1147.  
  1148.                 const CommunicationChannel::Ptr targetChannel = comm.channel;
  1149.                 if (channel->GetPriority() > targetChannel->GetPriority())
  1150.                 {
  1151.                         bool commRemoved = false;
  1152.                         if (channel->GetType() == SCommunicationChannelParams::Personal)
  1153.                         {
  1154.                                 if (request.actorID == comm.actorID)
  1155.                                 {
  1156.                                         commRemoved = true;
  1157.                                 }
  1158.                         }
  1159.                         //For group/global assume it should be replaced
  1160.                         else
  1161.                         {
  1162.                                 commRemoved = true;
  1163.                         }
  1164.  
  1165.                         if (commRemoved)
  1166.                         {
  1167.                                 //Make sure to flush the animation signal/action of the target actor if the new communication has an animation
  1168.                                 if (!comm.animName.empty())
  1169.                                 {
  1170.                                         SendAnimationGraphReset(request.actorID);
  1171.                                 }
  1172.                                 //If the channel is no longer playing a communication, but still has an imposed silence time, then reset the silence to the flush time now
  1173.                                 if (!channel->IsOccupied() && !channel->IsFree())
  1174.                                         channel->ResetSilence();
  1175.  
  1176.                                 m_unfinalized[commIndex] = m_unfinalized.back();
  1177.                                 m_unfinalized.pop_back();
  1178.                                 continue;
  1179.                         }
  1180.                 }
  1181.                 //Check the anim graph state against this animation. If it doesn't match, then this unfinalized comm is now finalized and can be removed.
  1182.                 else if (!comm.animName.empty() && !CheckAnimationGraphState(request.actorID, comm.animName))
  1183.                 {
  1184.                         m_unfinalized[commIndex] = m_unfinalized.back();
  1185.                         m_unfinalized.pop_back();
  1186.                         continue;
  1187.                 }
  1188.  
  1189.                 ++commIndex;
  1190.         }
  1191. }
  1192.  
  1193. bool CCommunicationManager::CheckAnimationGraphState(EntityId actorId, const string& name)
  1194. {
  1195.         IEntity* entity = gEnv->pEntitySystem->GetEntity(actorId);
  1196.         IAIObject* aiObject = entity ? entity->GetAI() : 0;
  1197.  
  1198.         if (IAIActorProxy* aiProxy = aiObject ? aiObject->GetProxy() : 0)
  1199.         {
  1200.                 IAICommunicationHandler* commHandler = aiProxy->GetCommunicationHandler();
  1201.  
  1202.                 return commHandler->IsInAGState(name.c_str());
  1203.         }
  1204.  
  1205.         return false;
  1206. }
  1207.  
  1208. void CCommunicationManager::SendAnimationGraphReset(EntityId actorId)
  1209. {
  1210.  
  1211.         IEntity* entity = gEnv->pEntitySystem->GetEntity(actorId);
  1212.         IAIObject* aiObject = entity ? entity->GetAI() : 0;
  1213.  
  1214.         if (IAIActorProxy* aiProxy = aiObject ? aiObject->GetProxy() : 0)
  1215.         {
  1216.                 IAICommunicationHandler* commHandler = aiProxy->GetCommunicationHandler();
  1217.  
  1218.                 commHandler->ResetAnimationState();
  1219.         }
  1220.  
  1221. }
  1222.  
  1223. void CCommunicationManager::StopCommunication(const CommPlayID& playID)
  1224. {
  1225.         FUNCTION_PROFILER(GetISystem(), PROFILE_AI);
  1226.  
  1227.         if (m_player.IsPlaying(playID))
  1228.         {
  1229.                 PlayingCommunications::iterator it = m_playing.find(playID);
  1230.                 assert(it != m_playing.end());
  1231.  
  1232.                 PlayingCommunication& playing = it->second;
  1233.  
  1234.                 if (playing.eventListener)
  1235.                         playing.eventListener->OnCommunicationEvent(CommunicationCancelled, playing.actorID, playID);
  1236.  
  1237.                 UpdateGlobalListeners(CommunicationCancelled, playing.actorID, m_player.GetCommunicationID(playID));
  1238.  
  1239.                 if (gAIEnv.CVars.DebugDrawCommunication == 5)
  1240.                 {
  1241.                         CommID commID = m_player.GetCommunicationID(playID);
  1242.                         CryLogAlways("CommunicationManager::StopCommunication: %s[%u] as playID[%u]", GetCommunicationName(commID), commID.id, playID.id);
  1243.                 }
  1244.  
  1245.                 //Erasing first will corrupt the playID handle.
  1246.                 //m_playing.erase(it); // erase before stopping - to simplify handling in the OnCommunicationFinished
  1247.  
  1248.                 m_player.Stop(playID);
  1249.         }
  1250.  
  1251.         if (RemoveFromQueue(m_orderedQueue, playID))
  1252.                 return;
  1253.  
  1254.         if (RemoveFromQueue(m_unorderedQueue, playID))
  1255.                 return;
  1256. }
  1257.  
  1258. bool CCommunicationManager::IsPlaying(const CommPlayID& playID, float* timeRemaining) const
  1259. {
  1260.         return m_player.IsPlaying(playID, timeRemaining);
  1261. }
  1262.  
  1263. bool CCommunicationManager::IsQueued(const CommPlayID& playID, float* estimatedWaitTime) const
  1264. {
  1265.         QueuedCommunications::const_iterator oit = m_orderedQueue.begin();
  1266.         QueuedCommunications::const_iterator oend = m_orderedQueue.end();
  1267.  
  1268.         for (; oit != oend; ++oit)
  1269.         {
  1270.                 if (oit->playID == playID)
  1271.                         return true;
  1272.         }
  1273.  
  1274.         QueuedCommunications::const_iterator uit = m_unorderedQueue.begin();
  1275.         QueuedCommunications::const_iterator uend = m_unorderedQueue.end();
  1276.  
  1277.         for (; uit != uend; ++uit)
  1278.         {
  1279.                 if (uit->playID == playID)
  1280.                         return true;
  1281.         }
  1282.  
  1283.         return false;
  1284. }
  1285.  
  1286. void CCommunicationManager::OnCommunicationFinished(const CommPlayID& playID, uint8 stateFlags)
  1287. {
  1288.         PlayingCommunications::iterator it = m_playing.find(playID);
  1289.         if (it != m_playing.end())
  1290.         {
  1291.                 PlayingCommunication& playing = it->second;
  1292.  
  1293.                 if (!playing.skipSound)
  1294.                 {
  1295.                         assert(!playing.channel->IsFree());
  1296.                         playing.channel->Occupy(false, playing.minSilence);
  1297.                 }
  1298.  
  1299.                 if (playing.eventListener)
  1300.                         playing.eventListener->OnCommunicationEvent(CommunicationFinished, playing.actorID, playID);
  1301.  
  1302.                 UpdateGlobalListeners(CommunicationFinished, playing.actorID, m_player.GetCommunicationID(playID));
  1303.  
  1304.                 if (gAIEnv.CVars.DebugDrawCommunication == 5)
  1305.                 {
  1306.                         CommID commID = m_player.GetCommunicationID(playID);
  1307.                         CryLogAlways("CommunicationManager::OnCommunicationFinished: %s[%u] as playID[%u]", GetCommunicationName(commID), commID.id, playID.id);
  1308.                 }
  1309.  
  1310.                 if (stateFlags != CommunicationPlayer::PlayState::FinishedAll)
  1311.                 {
  1312.                         m_unfinalized.push_back(playing);
  1313.                 }
  1314.  
  1315.                 m_playing.erase(it);
  1316.  
  1317.         }
  1318.         else if (gAIEnv.CVars.DebugDrawCommunication == 5)
  1319.         {
  1320.                 CommID commID = m_player.GetCommunicationID(playID);
  1321.                 CryWarning(VALIDATOR_MODULE_AI, VALIDATOR_WARNING, "CommunicationManager::OnCommunicationFinished - for unknown playID: %s[%u] as playID[%u]", GetCommunicationName(commID), commID.id, playID.id);
  1322.         }
  1323. }
  1324.  
  1325. const CCommunicationManager::CommunicationsConfig& CCommunicationManager::GetConfig(const CommConfigID& configID) const
  1326. {
  1327.         Configs::const_iterator cit = m_configs.find(configID);
  1328.         if (cit == m_configs.end())
  1329.         {
  1330.                 static CommunicationsConfig empty;
  1331.                 return empty;
  1332.         }
  1333.  
  1334.         const CommunicationsConfig& config = cit->second;
  1335.  
  1336.         return config;
  1337. }
  1338.  
  1339. CommunicationTestManager& CCommunicationManager::GetTestManager()
  1340. {
  1341.         return m_testManager;
  1342. }
  1343.  
  1344. bool CCommunicationManager::Play(const CommPlayID& playID, SCommunicationRequest& request,
  1345.                                  const CommunicationChannel::Ptr& channel, SCommunication& comm)
  1346. {
  1347.         bool playResult = false;
  1348.  
  1349.         UpdateStateOfInternalVariables(request);
  1350.  
  1351.         uint32 variation = 0;
  1352.         bool canChooseVariation = ChooseVariation(comm, comm.choiceMethod, 0, variation);
  1353.  
  1354.         if (!canChooseVariation)
  1355.         {
  1356.                 // If we cannot choose any variation let's try to reset the history and choose again
  1357.                 // because maybe with the current variables state only the default variations are available
  1358.                 // and they were already all played
  1359.                 ResetHistory();
  1360.                 canChooseVariation = ChooseVariation(comm, comm.choiceMethod, 0, variation);
  1361.         }
  1362.  
  1363.         if (canChooseVariation && m_player.Play(playID, request, comm, variation, this, (void*)(EXPAND_PTR)request.channelID.id))
  1364.         {
  1365.                 if (gAIEnv.CVars.RecordCommunicationStats > 0)
  1366.                 {
  1367.                         //Record the request here if statistics are being generated
  1368.                         CommDebugCount& commCount = m_debugStatisticsMap[CommKeys(request.configID, request.commID)];
  1369.                         ++commCount.playCount;
  1370.                 }
  1371.  
  1372.                 UpdateHistory(comm, variation);
  1373.  
  1374.                 //If sound component of readability was skipped then don't occupy any channel
  1375.                 //Also skip if the readability contained no sound/voice
  1376.                 const SCommunicationVariation& variationEntry = comm.variations[variation];
  1377.                 if (variationEntry.soundName.empty() && variationEntry.voiceName.empty())
  1378.                         request.skipCommSound = true;
  1379.  
  1380.                 if (!request.skipCommSound)
  1381.                 {
  1382.                         channel->Occupy(true);
  1383.  
  1384.                         //Impose minimum actor silence time based on channel's param
  1385.                         float actorSilence = channel->GetActorSilence();
  1386.                         if (actorSilence > 0)
  1387.                         {
  1388.                                 SetRestrictedDuration(request.actorID, actorSilence, 0.0f);
  1389.                         }
  1390.                 }
  1391.  
  1392.                 PlayingCommunication& playing = stl::map_insert_or_get(m_playing, playID, PlayingCommunication());
  1393.                 playing.actorID = request.actorID;
  1394.                 playing.channel = channel;
  1395.                 playing.eventListener = request.eventListener;
  1396.                 playing.animName = comm.variations[variation].animationName;
  1397.                 playing.skipSound = request.skipCommSound;
  1398.                 playing.minSilence = request.minSilence;
  1399.                 playing.startTime = gEnv->pTimer->GetCurrTime();
  1400.  
  1401.                 if (request.eventListener)
  1402.                         request.eventListener->OnCommunicationEvent(CommunicationStarted, request.actorID, playID);
  1403.  
  1404.                 UpdateGlobalListeners(CommunicationStarted, playing.actorID, m_player.GetCommunicationID(playID));
  1405.  
  1406.                 playResult = true;
  1407.         }
  1408.  
  1409.         if (gAIEnv.CVars.DebugDrawCommunication == 5 || gAIEnv.CVars.DebugDrawCommunication == 6)
  1410.         {
  1411.                 stack_string communicationPlayResult = canChooseVariation ? "PLAYED" : "NOT PLAYED";
  1412.                 stack_string variationIndex;
  1413.                 if (canChooseVariation)
  1414.                 {
  1415.                         variationIndex.Format("(Variation index %u)", variation);
  1416.                 }
  1417.                 else
  1418.                 {
  1419.                         variationIndex.Format("(The choice of a variation didn't return any valid result)");
  1420.                 }
  1421.                 CryLogAlways("Playing Communication '%s' Status=%s: [%u] as playID[%u] %s",
  1422.                              GetCommunicationName(request.commID), communicationPlayResult.c_str(), request.commID.id, playID.id, variationIndex.c_str());
  1423.         }
  1424.  
  1425.         ResetStateOfInternalVariables();
  1426.  
  1427.         return playResult;
  1428. }
  1429.  
  1430. void CCommunicationManager::FlushQueue(QueuedCommunications& queue, const CommunicationChannel::Ptr& channel, EntityId targetId)
  1431. {
  1432.         QueuedCommunications::iterator qit = queue.begin();
  1433.         QueuedCommunications::iterator end = queue.end();
  1434.  
  1435.         while (qit != end)
  1436.         {
  1437.                 QueuedCommunication& queued = *qit;
  1438.  
  1439.                 CommunicationChannel::Ptr targetChannel = m_channels.GetChannel(queued.request.channelID, queued.request.actorID);
  1440.                 if (channel->GetPriority() > targetChannel->GetPriority())
  1441.                 {
  1442.                         bool commFlushed = false;
  1443.                         if (channel->GetType() == SCommunicationChannelParams::Personal)
  1444.                         {
  1445.                                 if (queued.request.actorID == targetId)
  1446.                                 {
  1447.                                         commFlushed = true;
  1448.                                 }
  1449.                         }
  1450.                         //For group/global assume it should be flushed
  1451.                         else
  1452.                         {
  1453.                                 commFlushed = true;
  1454.                         }
  1455.  
  1456.                         if (commFlushed)
  1457.                         {
  1458.                                 if (queued.request.eventListener)
  1459.                                         queued.request.eventListener->OnCommunicationEvent(CommunicationCancelled, queued.request.actorID, queued.playID);
  1460.  
  1461.                                 UpdateGlobalListeners(CommunicationCancelled, queued.request.actorID, queued.request.commID);
  1462.  
  1463.                                 qit = queue.erase(qit);
  1464.                                 continue;
  1465.                         }
  1466.                 }
  1467.  
  1468.                 ++qit;
  1469.         }
  1470.  
  1471. }
  1472.  
  1473. void CCommunicationManager::Queue(QueuedCommunications& queue,
  1474.                                   const CommPlayID& playID,
  1475.                                   const SCommunicationRequest& request)
  1476. {
  1477.         assert(!IsQueued(playID, 0));
  1478.  
  1479.         queue.push_back(QueuedCommunication());
  1480.         QueuedCommunication& back = queue.back();
  1481.  
  1482.         back.playID = playID;
  1483.         back.age = 0.0f;
  1484.         back.request = request;
  1485.  
  1486.         if (request.eventListener)
  1487.                 request.eventListener->OnCommunicationEvent(CommunicationQueued, request.actorID, playID);
  1488.  
  1489.         UpdateGlobalListeners(CommunicationQueued, request.actorID, request.commID);
  1490.  
  1491.         assert((m_unorderedQueue.size() + m_orderedQueue.size()) < 64);
  1492. }
  1493.  
  1494. bool CCommunicationManager::RemoveFromQueue(QueuedCommunications& queue, const CommPlayID& playID)
  1495. {
  1496.         QueuedCommunications::iterator it = queue.begin();
  1497.         QueuedCommunications::iterator end = queue.end();
  1498.  
  1499.         for (; it != end; ++it)
  1500.         {
  1501.                 QueuedCommunication& queued = *it;
  1502.  
  1503.                 if (queued.playID == playID)
  1504.                 {
  1505.                         if (queued.request.eventListener)
  1506.                                 queued.request.eventListener->OnCommunicationEvent(CommunicationCancelled, queued.request.actorID, queued.playID);
  1507.  
  1508.                         UpdateGlobalListeners(CommunicationCancelled, queued.request.actorID, queued.request.commID);
  1509.  
  1510.                         queue.erase(it);
  1511.                         return true;
  1512.                 }
  1513.         }
  1514.  
  1515.         return false;
  1516. }
  1517.  
  1518. void CCommunicationManager::UpdateQueue(QueuedCommunications& queue, float updateTime)
  1519. {
  1520.         QueuedCommunications::iterator it = queue.begin();
  1521.         QueuedCommunications::iterator end = queue.end();
  1522.  
  1523.         for (; it != end; )
  1524.         {
  1525.                 QueuedCommunication& queued = *it;
  1526.                 queued.age += updateTime;
  1527.  
  1528.                 if (queued.age <= queued.request.contextExpiry)
  1529.                         ++it;
  1530.                 else
  1531.                 {
  1532.                         if (queued.request.eventListener)
  1533.                                 queued.request.eventListener->OnCommunicationEvent(CommunicationExpired, queued.request.actorID, queued.playID);
  1534.  
  1535.                         UpdateGlobalListeners(CommunicationExpired, queued.request.actorID, queued.request.commID);
  1536.  
  1537.                         QueuedCommunications::iterator erased = it++;
  1538.                         queue.erase(erased);
  1539.                 }
  1540.         }
  1541. }
  1542.  
  1543. bool CCommunicationManager::PlayFromQueue(QueuedCommunication& queued)
  1544. {
  1545.         // sanity checks are performed before playing from the queue
  1546.         Configs::iterator cit = m_configs.find(queued.request.configID);
  1547.         CommunicationsConfig& config = cit->second;
  1548.  
  1549.         Communications::iterator commIt = config.comms.find(queued.request.commID);
  1550.         SCommunication& comm = commIt->second;
  1551.  
  1552.         CommunicationChannel::Ptr channel = m_channels.GetChannel(queued.request.channelID, queued.request.actorID);
  1553.         if (!channel->IsFree())
  1554.                 return false;
  1555.  
  1556.         if (IsAnimationRestricted(queued.request.actorID))
  1557.         {
  1558.                 queued.request.skipCommAnimation = true;
  1559.         }
  1560.  
  1561.         if (!channel->IgnoresActorSilence())
  1562.         {
  1563.                 if (IsVoiceRestricted(queued.request.actorID))
  1564.                 {
  1565.                         queued.request.skipCommSound = true;
  1566.                 }
  1567.         }
  1568.  
  1569.         //If there is still a component to play
  1570.         if (!queued.request.skipCommAnimation || !queued.request.skipCommSound)
  1571.         {
  1572.                 Play(queued.playID, queued.request, channel, comm);
  1573.         }
  1574.         // Else do nothing, drop this from the queue, as the actor is restricted, try the next entry
  1575.  
  1576.         return true;
  1577. }
  1578.  
  1579. void CCommunicationManager::ProcessQueues()
  1580. {
  1581.         // Ordered queue has priority since it's usually more important
  1582.         while (!m_orderedQueue.empty())
  1583.         {
  1584.                 QueuedCommunication& queued = m_orderedQueue.front();
  1585.  
  1586.                 if (!PlayFromQueue(queued))
  1587.                         break;
  1588.  
  1589.                 m_orderedQueue.erase(m_orderedQueue.begin());
  1590.         }
  1591.  
  1592.         while (!m_unorderedQueue.empty())
  1593.         {
  1594.                 QueuedCommunication& queued = m_unorderedQueue.front();
  1595.  
  1596.                 if (!PlayFromQueue(queued))
  1597.                         break;
  1598.  
  1599.                 m_unorderedQueue.erase(m_unorderedQueue.begin());
  1600.         }
  1601. }
  1602.  
  1603. bool CCommunicationManager::ChooseVariation(const SCommunication& comm, const SCommunication::EVariationChoiceMethod method,
  1604.                                             const uint32 index, uint32& outputIndex) const
  1605. {
  1606.         const uint32 variationCount = comm.variations.size();
  1607.  
  1608.         switch (method)
  1609.         {
  1610.         case SCommunication::RandomSequence:
  1611.                 {
  1612.                         m_randomPool.resize(0);
  1613.  
  1614.                         for (uint32 i = 0; i < variationCount; ++i)
  1615.                         {
  1616.                                 const bool canVariationBePlayed = CanVariationBePlayed(comm, i);
  1617.                                 if ((comm.history.played & (1 << i)) == 0 && canVariationBePlayed)
  1618.                                         m_randomPool.push_back(i);
  1619.                         }
  1620.  
  1621.                         const uint32 size = m_randomPool.size();
  1622.                         if (!m_randomPool.empty())
  1623.                         {
  1624.                                 outputIndex = m_randomPool[cry_random(0U, size - 1)];
  1625.                                 return true;
  1626.                         }
  1627.                         return false;
  1628.                 }
  1629.                 break;
  1630.         case SCommunication::Sequence:
  1631.                 {
  1632.                         uint32 played = comm.history.played;
  1633.                         uint32 next = 0;
  1634.  
  1635.                         while (played >>= 1)
  1636.                                 ++next;
  1637.  
  1638.                         // We arrived to the first element that we didn't play
  1639.                         // Now check which is the first element we CAN play
  1640.                         while (next < variationCount && !CanVariationBePlayed(comm, next))
  1641.                         {
  1642.                                 ++next;
  1643.                         }
  1644.  
  1645.                         outputIndex = next;
  1646.                         return true;
  1647.                 }
  1648.                 break;
  1649.         case SCommunication::Match:
  1650.                 {
  1651.                         outputIndex = index;
  1652.                         if (outputIndex < variationCount && CanVariationBePlayed(comm, outputIndex))
  1653.                         {
  1654.                                 return true;
  1655.                         }
  1656.                         else
  1657.                         {
  1658.                                 outputIndex = index % variationCount;
  1659.                                 if (CanVariationBePlayed(comm, outputIndex))
  1660.                                         return true;
  1661.                                 else
  1662.                                         return false;
  1663.                         }
  1664.                 }
  1665.                 break;
  1666.         default:
  1667.         case SCommunication::Random:
  1668.                 {
  1669.                         m_randomPool.resize(0);
  1670.  
  1671.                         for (uint32 i = 0; i < variationCount; ++i)
  1672.                         {
  1673.                                 const bool canVariationBePlayed = CanVariationBePlayed(comm, i);
  1674.                                 if (canVariationBePlayed)
  1675.                                         m_randomPool.push_back(i);
  1676.                         }
  1677.  
  1678.                         uint32 size = m_randomPool.size();
  1679.                         if (!m_randomPool.empty())
  1680.                         {
  1681.                                 outputIndex = m_randomPool[cry_random(0U, size - 1)];
  1682.                                 return true;
  1683.                         }
  1684.                         return false;
  1685.                 }
  1686.         }
  1687. }
  1688.  
  1689. bool CCommunicationManager::CanVariationBePlayed(const SCommunication& comm, const uint32 variationIndex) const
  1690. {
  1691.         if (variationIndex < comm.variations.size())
  1692.         {
  1693.                 const SCommunicationVariation& variation = comm.variations[variationIndex];
  1694.                 if (variation.condition.get())
  1695.                         return variation.condition->Evaluate(m_variables);
  1696.                 else
  1697.                         return true;
  1698.         }
  1699.  
  1700.         return false;
  1701. }
  1702.  
  1703. void CCommunicationManager::UpdateHistory(SCommunication& comm, uint32 variation)
  1704. {
  1705.         uint32 variationCount = comm.variations.size();
  1706.         assert(variation < variationCount);
  1707.  
  1708.         comm.history.played |= 1 << variation;
  1709.  
  1710.         // Reset everything except the one currently played,
  1711.         // to prevent it from being picked again next play
  1712.         if (variationCount > 1)
  1713.         {
  1714.                 if ((comm.history.played & ((1 << variationCount) - 1)) == comm.history.played)
  1715.                         comm.history.played = 1 << variation;
  1716.         }
  1717. }
  1718.  
  1719. void CCommunicationManager::SetRestrictedDuration(EntityId actorId, float voiceDuration, float animDuration)
  1720. {
  1721.         SRestrictedActorParams& actorParams = m_restrictedActors[actorId];
  1722.         if (voiceDuration > 0.0f)
  1723.         {
  1724.                 actorParams.m_voiceRestrictedTime = voiceDuration;
  1725.         }
  1726.         if (animDuration > 0.0f)
  1727.         {
  1728.                 actorParams.m_animRestrictedTime = animDuration;
  1729.         }
  1730. }
  1731.  
  1732. void CCommunicationManager::AddActorRestriction(EntityId actorId, bool restrictVoice, bool restrictAnimation)
  1733. {
  1734.         SRestrictedActorParams& actorParams = m_restrictedActors[actorId];
  1735.  
  1736.         if (restrictVoice)
  1737.         {
  1738.                 ++actorParams.m_voiceRestricted;
  1739.         }
  1740.         if (restrictAnimation)
  1741.         {
  1742.                 ++actorParams.m_animRestricted;
  1743.         }
  1744. }
  1745.  
  1746. void CCommunicationManager::RemoveActorRestriction(EntityId actorId, bool unrestrictVoice, bool unrestrictAnimation)
  1747. {
  1748.         TRestrictedActorMap::iterator foundActor = m_restrictedActors.find(actorId);
  1749.  
  1750.         //If removing the restriction, then erase the actor from the restricted map
  1751.         if (foundActor != m_restrictedActors.end())
  1752.         {
  1753.                 SRestrictedActorParams& params = foundActor->second;
  1754.  
  1755.                 if (unrestrictVoice)
  1756.                 {
  1757.                         --params.m_voiceRestricted;
  1758.                 }
  1759.  
  1760.                 if (unrestrictAnimation)
  1761.                 {
  1762.                         --params.m_animRestricted;
  1763.                 }
  1764.                 //Next update call will handle removal of now unrestricted actors
  1765.                 assert(params.m_voiceRestricted >= 0 && params.m_animRestricted >= 0);
  1766.         }
  1767. }
  1768.  
  1769. void CCommunicationManager::SetVariableValue(const char* variableName, const bool newVariableValue)
  1770. {
  1771.         Variables::VariableID variableId = Variables::GetVariableID(variableName);
  1772.         m_variables.SetVariable(variableId, newVariableValue);
  1773. }
  1774.  
  1775. void CCommunicationManager::GetVariablesNames(const char** variableNames, const size_t maxSize, size_t& actualSize) const
  1776. {
  1777.         m_variablesDeclaration.GetVariablesNames(variableNames, maxSize, actualSize);
  1778. }
  1779.  
  1780. void CCommunicationManager::UpdateActorRestrictions(float updateTime)
  1781. {
  1782.         TRestrictedActorMap::iterator actorIt = m_restrictedActors.begin();
  1783.         TRestrictedActorMap::iterator endIt = m_restrictedActors.end();
  1784.  
  1785.         while (actorIt != endIt)
  1786.         {
  1787.                 SRestrictedActorParams& actorParams = actorIt->second;
  1788.                 actorParams.Update(updateTime);
  1789.  
  1790.                 if (!actorParams.IsRestricted())
  1791.                 {
  1792.                         m_restrictedActors.erase(actorIt++);
  1793.                         continue;
  1794.                 }
  1795.  
  1796.                 ++actorIt;
  1797.         }
  1798. }
  1799.  
  1800. bool CCommunicationManager::IsVoiceRestricted(EntityId actorId)
  1801. {
  1802.         TRestrictedActorMap::const_iterator foundActor = m_restrictedActors.find(actorId);
  1803.  
  1804.         if (foundActor != m_restrictedActors.end())
  1805.         {
  1806.                 const SRestrictedActorParams& actorParams = foundActor->second;
  1807.                 return actorParams.IsVoiceRestricted();
  1808.         }
  1809.  
  1810.         return false;
  1811. }
  1812.  
  1813. bool CCommunicationManager::IsAnimationRestricted(EntityId actorId)
  1814. {
  1815.         TRestrictedActorMap::const_iterator foundActor = m_restrictedActors.find(actorId);
  1816.  
  1817.         if (foundActor != m_restrictedActors.end())
  1818.         {
  1819.                 const SRestrictedActorParams& actorParams = foundActor->second;
  1820.                 return actorParams.IsAnimationRestricted();
  1821.         }
  1822.  
  1823.         return false;
  1824. }
  1825.  
  1826. //------------------------------------------------------------------------------------------------------------------------
  1827. void CCommunicationManager::GetActorData(EntityId actorId, SActorReadabilitySettings& actorReadabilitySettings)
  1828. {
  1829.         TActorReadabilityProperties::iterator ait = m_actorPropertiesMap.find(actorId);
  1830.  
  1831.         //Check here to see if the actor already retrieved its properties. If so just return that data
  1832.         if (ait != m_actorPropertiesMap.end())
  1833.         {
  1834.                 actorReadabilitySettings = ait->second;
  1835.                 return;
  1836.         }
  1837.  
  1838.         IEntity* pEntity = gEnv->pEntitySystem->GetEntity(actorId);
  1839.  
  1840.         SActorReadabilitySettings tempActorReadabilitySettings;
  1841.  
  1842.         if (IEntityArchetype* pEntityArchetype = pEntity->GetArchetype())
  1843.         {
  1844.                 if (IScriptTable* pProperties = pEntityArchetype->GetProperties())
  1845.                 {
  1846.                         ReadDataFromTable(pProperties, tempActorReadabilitySettings);
  1847.                         actorReadabilitySettings = tempActorReadabilitySettings;
  1848.                 }
  1849.         }
  1850.  
  1851.         SmartScriptTable ssInstanceTable;
  1852.         bool bFound = pEntity->GetScriptTable()->GetValue("PropertiesInstance", ssInstanceTable);
  1853.         if (!bFound)
  1854.         {
  1855.                 bFound = pEntity->GetScriptTable()->GetValue("Properties", ssInstanceTable);
  1856.         }
  1857.  
  1858.         if (bFound)
  1859.         {
  1860.                 SmartScriptTable ssReadabilityInstanceTable;
  1861.                 if (ssInstanceTable->GetValue("Readability", ssReadabilityInstanceTable))
  1862.                 {
  1863.                         bool bOverrideArchetype = true;
  1864.                         bool bExists = ssReadabilityInstanceTable->GetValue("bOverrideArchetype", bOverrideArchetype);
  1865.  
  1866.                         if (!bExists || bOverrideArchetype)
  1867.                         {
  1868.                                 ReadDataFromTable(ssInstanceTable, tempActorReadabilitySettings);
  1869.                                 actorReadabilitySettings = tempActorReadabilitySettings;
  1870.                         }
  1871.                 }
  1872.         }
  1873.  
  1874.         m_actorPropertiesMap[actorId] = actorReadabilitySettings;
  1875. }
  1876.  
  1877. //------------------------------------------------------------------------------------------------------------------------
  1878. void CCommunicationManager::ReadDataFromTable(const SmartScriptTable& ssTable, SActorReadabilitySettings& actorReadabilitySettings)
  1879. {
  1880.         SmartScriptTable ssReadabilityTable;
  1881.  
  1882.         if (ssTable->GetValue("Readability", ssReadabilityTable))
  1883.         {
  1884.                 ssReadabilityTable->GetValue("bIgnoreAnimations", actorReadabilitySettings.m_bIgnoreAnimations);
  1885.                 ssReadabilityTable->GetValue("bIgnoreVoice", actorReadabilitySettings.m_bIgnoreVoice);
  1886.         }
  1887. }
  1888.  
  1889. void CCommunicationManager::RemoveInstanceListener(const CommPlayID& playID)
  1890. {
  1891.         PlayingCommunications::iterator it = m_playing.find(playID);
  1892.         if (it != m_playing.end() && it->second.eventListener)
  1893.                 it->second.eventListener = NULL;
  1894.  
  1895.         //Could also be in one of the queues.
  1896.  
  1897.         for (QueuedCommunications::iterator ordIt = m_orderedQueue.begin(); ordIt != m_orderedQueue.end(); ++ordIt)
  1898.         {
  1899.                 if (playID == ordIt->playID)
  1900.                 {
  1901.                         ordIt->request.eventListener = NULL;
  1902.                         break;
  1903.                 }
  1904.         }
  1905.  
  1906.         for (QueuedCommunications::iterator unordIt = m_unorderedQueue.begin(); unordIt != m_unorderedQueue.end(); ++unordIt)
  1907.         {
  1908.                 if (playID == unordIt->playID)
  1909.                 {
  1910.                         unordIt->request.eventListener = NULL;
  1911.                         break;
  1912.                 }
  1913.         }
  1914.  
  1915. }
  1916.  
  1917. void CCommunicationManager::WriteStatistics()
  1918. {
  1919. #if !defined(_RELEASE)
  1920.         static const char* logFilename = "communication_statistics.txt";
  1921.  
  1922.         #if defined(USE_FILE_HANDLE_CACHE)
  1923.         FILE* pLogFile = ::fopen(logFilename, "wt", FileIoWrapper::GENERAL, true);
  1924.         #else
  1925.         FILE* pLogFile = fxopen(logFilename, "wt");
  1926.         #endif
  1927.  
  1928.         CryLogAlways("Dumping Communication Statistics log to '%s'\n", logFilename);
  1929.  
  1930.         string lastConfig;
  1931.         for (TDebugMapStatistics::const_iterator statIt = m_debugStatisticsMap.begin(); statIt != m_debugStatisticsMap.end(); ++statIt)
  1932.         {
  1933.                 string currentConfig = GetConfig(statIt->first.configId).name;
  1934.                 //Add a title line to separate configs' stats
  1935.                 if (currentConfig != lastConfig)
  1936.                 {
  1937.                         if (!lastConfig.empty())
  1938.                         {
  1939.                                 fprintf(pLogFile, "\n");
  1940.                         }
  1941.                         fprintf(pLogFile, "Config: %s Requested Played\n", currentConfig.c_str());
  1942.                         lastConfig = currentConfig;
  1943.                 }
  1944.                 const char* pName = GetCommunicationName(statIt->first.commId);
  1945.                 fprintf(pLogFile, "Comm: %s %u %u\n", pName, statIt->second.requestCount, statIt->second.playCount);
  1946.         }
  1947.  
  1948.         fclose(pLogFile);
  1949.  
  1950.         m_debugStatisticsMap.clear();
  1951. #endif
  1952. }
  1953.  
  1954. void CCommunicationManager::CullPlayingCommunications()
  1955. {
  1956.         // If communications have been playing for some
  1957.         // time we consider it stuck and remove it.
  1958.  
  1959.         const float maxTimeAllowedPlaying = 7.0f;
  1960.         float now = gEnv->pTimer->GetCurrTime();
  1961.  
  1962.         PlayingCommunications::iterator it = m_playing.begin();
  1963.         PlayingCommunications::iterator end = m_playing.end();
  1964.  
  1965.         for (; it != end; ++it)
  1966.         {
  1967.                 PlayingCommunication& comm = it->second;
  1968.  
  1969.                 float elapsed = now - comm.startTime;
  1970.  
  1971.                 if (elapsed > maxTimeAllowedPlaying)
  1972.                 {
  1973.                         const CommPlayID& playID = it->first;
  1974.  
  1975.                         StopCommunication(playID);
  1976.  
  1977.                         // It's important that we return here because the m_playing
  1978.                         // container has been modified and the iterators might no
  1979.                         // longer be valid.
  1980.                         return;
  1981.                 }
  1982.         }
  1983. }
  1984.  
  1985. void CCommunicationManager::UpdateStateOfInternalVariables(const SCommunicationRequest& request)
  1986. {
  1987.         IEntity* pEntity = gEnv->pEntitySystem->GetEntity(request.actorID);
  1988.         if (pEntity)
  1989.         {
  1990.                 CAIActor* pAIActor = CastToCAIActorSafe(pEntity->GetAI());
  1991.                 if (pAIActor)
  1992.                 {
  1993.                         const IAIObject* pAttTarget = pAIActor->GetAttentionTarget();
  1994.                         if (pAttTarget)
  1995.                         {
  1996.                                 UpdateStateOfTargetAboveBelowVariables(pEntity->GetPos(), pAttTarget->GetPos());
  1997.                         }
  1998.                 }
  1999.         }
  2000. }
  2001.  
  2002. void CCommunicationManager::UpdateStateOfTargetAboveBelowVariables(const Vec3& entityPos, const Vec3& targetPos)
  2003. {
  2004.         const float heightThreshold = gAIEnv.CVars.CommunicationManagerHeightThresholdForTargetPosition;
  2005.         const float heightDifference = targetPos.z - entityPos.z;
  2006.         if (heightDifference > heightThreshold)
  2007.         {
  2008.                 SetVariableValue(m_kTargetIsAbove_VariableName, true);
  2009.         }
  2010.         else if (heightDifference < -heightThreshold)
  2011.         {
  2012.                 SetVariableValue(m_kTargetIsBelow_VariableName, true);
  2013.         }
  2014. }
  2015.  
  2016. void CCommunicationManager::ResetStateOfInternalVariables()
  2017. {
  2018.         // Player is above
  2019.         SetVariableValue(m_kTargetIsAbove_VariableName, false);
  2020.  
  2021.         // Player is below
  2022.         SetVariableValue(m_kTargetIsBelow_VariableName, false);
  2023. }
  2024.  
downloadCommunicationManager.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top