BVB Source Codes

CRYENGINE Show GoalPipeXMLReader.cpp Source code

Return Download CRYENGINE: download GoalPipeXMLReader.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 "GoalPipeXMLReader.h"
  5. #include "AILog.h"
  6. #include <CryAISystem/IAgent.h>
  7. #include "TacticalPointSystem/TacticalPointSystem.h"
  8.  
  9. CGoalPipeXMLReader::CGoalPipeXMLReader()
  10. {
  11.         m_dictBranchType.Add("IF_ACTIVE_GOALS", IF_ACTIVE_GOALS);
  12.         m_dictBranchType.Add("IF_ACTIVE_GOALS_HIDE", IF_ACTIVE_GOALS_HIDE);
  13.         m_dictBranchType.Add("IF_NO_PATH", IF_NO_PATH);
  14.         m_dictBranchType.Add("IF_PATH_STILL_FINDING", IF_PATH_STILL_FINDING);
  15.         m_dictBranchType.Add("IF_IS_HIDDEN", IF_IS_HIDDEN);
  16.         m_dictBranchType.Add("IF_CAN_HIDE", IF_CAN_HIDE);
  17.         m_dictBranchType.Add("IF_CANNOT_HIDE", IF_CANNOT_HIDE);
  18.         m_dictBranchType.Add("IF_STANCE_IS", IF_STANCE_IS);
  19.         m_dictBranchType.Add("IF_FIRE_IS", IF_FIRE_IS);
  20.         m_dictBranchType.Add("IF_HAS_FIRED", IF_HAS_FIRED);
  21.         m_dictBranchType.Add("IF_NO_LASTOP", IF_NO_LASTOP);
  22.         m_dictBranchType.Add("IF_SEES_LASTOP", IF_SEES_LASTOP);
  23.         m_dictBranchType.Add("IF_SEES_TARGET", IF_SEES_TARGET);
  24.         m_dictBranchType.Add("IF_CAN_SHOOT_TARGET", IF_CAN_SHOOT_TARGET);
  25.         m_dictBranchType.Add("IF_CAN_MELEE", IF_CAN_MELEE);
  26.         m_dictBranchType.Add("IF_NO_ENEMY_TARGET", IF_NO_ENEMY_TARGET);
  27.         m_dictBranchType.Add("IF_PATH_LONGER", IF_PATH_LONGER);
  28.         m_dictBranchType.Add("IF_PATH_SHORTER", IF_PATH_SHORTER);
  29.         m_dictBranchType.Add("IF_PATH_LONGER_RELATIVE", IF_PATH_LONGER_RELATIVE);
  30.         m_dictBranchType.Add("IF_NAV_WAYPOINT_HUMAN", IF_NAV_WAYPOINT_HUMAN);
  31.         m_dictBranchType.Add("IF_NAV_TRIANGULAR", IF_NAV_TRIANGULAR);
  32.         m_dictBranchType.Add("IF_TARGET_DIST_LESS", IF_TARGET_DIST_LESS);
  33.         m_dictBranchType.Add("IF_TARGET_DIST_LESS_ALONG_PATH", IF_TARGET_DIST_LESS_ALONG_PATH);
  34.         m_dictBranchType.Add("IF_TARGET_DIST_GREATER", IF_TARGET_DIST_GREATER);
  35.         m_dictBranchType.Add("IF_TARGET_IN_RANGE", IF_TARGET_IN_RANGE);
  36.         m_dictBranchType.Add("IF_TARGET_OUT_OF_RANGE", IF_TARGET_OUT_OF_RANGE);
  37.         m_dictBranchType.Add("IF_TARGET_TO_REFPOINT_DIST_LESS", IF_TARGET_TO_REFPOINT_DIST_LESS);
  38.         m_dictBranchType.Add("IF_TARGET_TO_REFPOINT_DIST_GREATER", IF_TARGET_TO_REFPOINT_DIST_GREATER);
  39.         m_dictBranchType.Add("IF_TARGET_LOST_TIME_MORE", IF_TARGET_LOST_TIME_MORE);
  40.         m_dictBranchType.Add("IF_TARGET_LOST_TIME_LESS", IF_TARGET_LOST_TIME_LESS);
  41.         m_dictBranchType.Add("IF_LASTOP_DIST_LESS", IF_LASTOP_DIST_LESS);
  42.         m_dictBranchType.Add("IF_LASTOP_DIST_LESS_ALONG_PATH", IF_LASTOP_DIST_LESS_ALONG_PATH);
  43.         m_dictBranchType.Add("IF_TARGET_MOVED_SINCE_START", IF_TARGET_MOVED_SINCE_START);
  44.         m_dictBranchType.Add("IF_TARGET_MOVED", IF_TARGET_MOVED);
  45.         m_dictBranchType.Add("IF_EXPOSED_TO_TARGET", IF_EXPOSED_TO_TARGET);
  46.         m_dictBranchType.Add("IF_COVER_COMPROMISED", IF_COVER_COMPROMISED);
  47.         m_dictBranchType.Add("IF_COVER_NOT_COMPROMISED", IF_COVER_NOT_COMPROMISED);
  48.         m_dictBranchType.Add("IF_COVER_SOFT", IF_COVER_SOFT);
  49.         m_dictBranchType.Add("IF_COVER_NOT_SOFT", IF_COVER_NOT_SOFT);
  50.         m_dictBranchType.Add("IF_CAN_SHOOT_TARGET_PRONED", IF_CAN_SHOOT_TARGET_PRONED);
  51.         m_dictBranchType.Add("IF_CAN_SHOOT_TARGET_CROUCHED", IF_CAN_SHOOT_TARGET_CROUCHED);
  52.         m_dictBranchType.Add("IF_CAN_SHOOT_TARGET_STANDING", IF_CAN_SHOOT_TARGET_STANDING);
  53.         m_dictBranchType.Add("IF_COVER_FIRE_ENABLED", IF_COVER_FIRE_ENABLED);
  54.         m_dictBranchType.Add("IF_RANDOM", IF_RANDOM);
  55.         m_dictBranchType.Add("IF_CHANCE", IF_RANDOM);
  56.         m_dictBranchType.Add("IF_LASTOP_FAILED", IF_LASTOP_FAILED);
  57.         m_dictBranchType.Add("IF_LASTOP_SUCCEED", IF_LASTOP_SUCCEED);
  58. }
  59.  
  60. bool CGoalPipeXMLReader::LoadGoalPipesFromXmlFile(const char* filename)
  61. {
  62.         const XmlNodeRef root = GetISystem()->LoadXmlFromFile(filename);
  63.         if (!root)
  64.         {
  65.                 AIError("Unable to load goal pipes XML file: %s", filename);
  66.                 return false;
  67.         }
  68.  
  69.         AILogLoading("Loading goal pipes XML file: %s...", filename);
  70.         return LoadGoalPipesFromXmlNode(root);
  71. }
  72.  
  73. bool CGoalPipeXMLReader::LoadGoalPipesFromXmlNode(const XmlNodeRef& root)
  74. {
  75.         for (int iGoalPipe = 0, nGoalPipes = root->getChildCount(); iGoalPipe < nGoalPipes; ++iGoalPipe)
  76.         {
  77.                 const XmlNodeRef goalPipeNode = root->getChild(iGoalPipe);
  78.                 if (goalPipeNode->isTag("GoalPipe"))
  79.                 {
  80.                         const char* szGoalPipeName = NULL;
  81.                         if (!goalPipeNode->getAttr("name", &szGoalPipeName))
  82.                         {
  83.                                 AIError("Encountered tag <GoalPipe> without attribute 'name'; skipping.");
  84.                                 continue;
  85.                         }
  86.  
  87.                         ParseGoalPipe(szGoalPipeName, goalPipeNode);
  88.                 }
  89.         }
  90.  
  91.         return true;
  92. }
  93.  
  94. void CGoalPipeXMLReader::ParseGoalOps(IGoalPipe* pGoalPipe, const XmlNodeRef& parentNode,
  95.                                       string sIfLabel, bool b_IfElseEnd_Halves_ReverseOrder)
  96. {
  97.         if (sIfLabel.empty())
  98.         {
  99.                 // We are NOT within If-tag; just parse all the goalops in order.
  100.  
  101.                 for (int iGoalOp = 0, nGoalOps = parentNode->getChildCount(); iGoalOp < nGoalOps; ++iGoalOp)
  102.                 {
  103.                         const XmlNodeRef goalOpNode = parentNode->getChild(iGoalOp);
  104.                         ParseGoalOp(pGoalPipe, goalOpNode);
  105.                 }
  106.  
  107.                 m_currentGrouping = IGoalPipe::eGT_NOGROUP;
  108.         }
  109.         else
  110.         {
  111.                 // We are within tag <IfOr>.  Conditional branch(-es) to szIfLabel has (have) already been added.
  112.                 // 1. Add the goalops AFTER tag <Else/>
  113.                 // 2. Add unconditional branch to the end (tag </If>)
  114.                 // 3. Add label szIfLabel
  115.                 // 4. Add the goalops BEFORE tag <Else/>
  116.                 // That is the reversed order used for tag <IfOr> (b_IfElseEnd_Halves_ReverseOrder == true)
  117.                 //
  118.                 // <IfAnd> (or simply <If>) is based on <IfOr> using formula 'NOT(A AND B) = NOT(A) OR NOT(B).
  119.                 // In this case, sections "AFTER" and "BEFORE" from above should be swapped.
  120.                 // Hence the need for parameter 'b_IfElseEnd_Halves_ReverseOrder'.
  121.  
  122.                 int nGoalOps = parentNode->getChildCount();
  123.                 int iElseIndex = nGoalOps;
  124.  
  125.                 for (int iGoalOp = 0; iGoalOp < nGoalOps; ++iGoalOp)
  126.                 {
  127.                         if (!stricmp(parentNode->getChild(iGoalOp)->getTag(), "Else"))
  128.                         {
  129.                                 iElseIndex = iGoalOp;
  130.                                 break;
  131.                         }
  132.                 }
  133.  
  134.                 if (b_IfElseEnd_Halves_ReverseOrder)
  135.                 {
  136.                         for (int iGoalOp = iElseIndex + 1; iGoalOp < nGoalOps; ++iGoalOp)
  137.                         {
  138.                                 const XmlNodeRef goalOpNode = parentNode->getChild(iGoalOp);
  139.                                 ParseGoalOp(pGoalPipe, goalOpNode);
  140.                         }
  141.                 }
  142.                 else
  143.                 {
  144.                         for (int iGoalOp = 0; iGoalOp < iElseIndex; ++iGoalOp)
  145.                         {
  146.                                 const XmlNodeRef goalOpNode = parentNode->getChild(iGoalOp);
  147.                                 ParseGoalOp(pGoalPipe, goalOpNode);
  148.                         }
  149.                 }
  150.  
  151.                 string sEndIfLabel = sIfLabel + "End";
  152.  
  153.                 GoalParameters params;
  154.                 params.nValue = BRANCH_ALWAYS;
  155.                 params.str = sEndIfLabel;
  156.                 pGoalPipe->PushGoal(eGO_BRANCH, false, IGoalPipe::eGT_NOGROUP, params);
  157.  
  158.                 pGoalPipe->PushLabel(sIfLabel.c_str());
  159.  
  160.                 if (b_IfElseEnd_Halves_ReverseOrder)
  161.                 {
  162.                         for (int iGoalOp = 0; iGoalOp < iElseIndex; ++iGoalOp)
  163.                         {
  164.                                 const XmlNodeRef goalOpNode = parentNode->getChild(iGoalOp);
  165.                                 ParseGoalOp(pGoalPipe, goalOpNode);
  166.                         }
  167.                 }
  168.                 else
  169.                 {
  170.                         for (int iGoalOp = iElseIndex + 1; iGoalOp < nGoalOps; ++iGoalOp)
  171.                         {
  172.                                 const XmlNodeRef goalOpNode = parentNode->getChild(iGoalOp);
  173.                                 ParseGoalOp(pGoalPipe, goalOpNode);
  174.                         }
  175.                 }
  176.  
  177.                 pGoalPipe->PushLabel(sEndIfLabel.c_str());
  178.         }
  179. }
  180.  
  181. void CGoalPipeXMLReader::ParseGoalOp(IGoalPipe* pGoalPipe, const XmlNodeRef& goalOpNode)
  182. {
  183.         GoalParameters params;
  184.  
  185.         const char* szGoalOpName = goalOpNode->getTag();
  186.  
  187.         if (!stricmp(szGoalOpName, "Else"))
  188.         {
  189.                 AIError("Misplaced 'Else' encountered.");
  190.                 return;
  191.         }
  192.  
  193.         if (!stricmp(szGoalOpName, "Group"))
  194.         {
  195.                 m_currentGrouping = IGoalPipe::eGT_GROUPED;
  196.                 ParseGoalOps(pGoalPipe, goalOpNode);
  197.                 return;
  198.         }
  199.  
  200.         if (!stricmp(szGoalOpName, "If") || !stricmp(szGoalOpName, "IfAnd") || !stricmp(szGoalOpName, "IfOr"))
  201.         {
  202.                 // <IfOr condition1 condition2 ...> ... <Else/> ... </IfOr> is converted to:
  203.                 // AI.PushGoal("branch", 0, sLabel, condition1);
  204.                 // AI.PushGoal("branch", 0, sLabel, condition2);
  205.                 // ...
  206.                 // Translation of section <Else/> ... </IfOr>
  207.                 // Goto label (sLabel + "End")
  208.                 // Label sLabel
  209.                 // Translation of section <IfOr> ... <Else/>
  210.                 // Label (sLabel + "End")
  211.  
  212.                 // <IfAnd> (or simply <If>) is based on <IfOr> using formula 'NOT(A AND B) = NOT(A) OR NOT(B).
  213.                 bool bOr = !stricmp(szGoalOpName, "IfOr");
  214.  
  215.                 string sLabel = GenerateUniqueLabelName();
  216.                 params.str = sLabel;
  217.  
  218.                 // Each attribute is a condition
  219.                 for (int i = 0, n = goalOpNode->getNumAttributes(); i < n; ++i)
  220.                 {
  221.                         params.fValueAux = -1.f;
  222.  
  223.                         const char* szKey;
  224.                         const char* szValue;
  225.                         goalOpNode->getAttributeByIndex(i, &szKey, &szValue);
  226.  
  227.                         if (!strnicmp(szKey, "not_", 4))
  228.                         {
  229.                                 szKey += 4;
  230.                                 params.nValue = bOr ? NOT : 0;  // Treat "not " as 'not' :) if the tag is <IfOr>
  231.                         }
  232.                         else
  233.                         {
  234.                                 params.nValue = bOr ? 0 : NOT;  // Treat "yes" as 'yes' :) if the tag is <IfOr>
  235.                         }
  236.  
  237.                         int nBranchType;
  238.                         if (!m_dictBranchType.Get(szKey, nBranchType))
  239.                         {
  240.                                 AIError("Unrecognized attribute no. %d of tag %s of goal pipe %s: %s; skipping.",
  241.                                         i, szGoalOpName, pGoalPipe->GetName(), szKey);
  242.                                 continue;
  243.                         }
  244.  
  245.                         params.nValue |= nBranchType;
  246.                         params.fValue = static_cast<float>(atof(szValue));
  247.  
  248.                         // See if we can get the 2nd parameter
  249.                         if (i + 1 < n)
  250.                         {
  251.                                 goalOpNode->getAttributeByIndex(i + 1, &szKey, &szValue);
  252.                                 if (!m_dictBranchType.Get(szKey, nBranchType))
  253.                                 {
  254.                                         params.fValueAux = static_cast<float>(atof(szValue));
  255.                                 }
  256.                         }
  257.  
  258.                         pGoalPipe->PushGoal(eGO_BRANCH, false, IGoalPipe::eGT_NOGROUP, params);
  259.                 }
  260.  
  261.                 ParseGoalOps(pGoalPipe, goalOpNode, sLabel.c_str(), bOr); // the label for half "Else-EndIf" of "If-Else-EndIf"
  262.  
  263.                 return;
  264.         }
  265.  
  266.         if (!stricmp(szGoalOpName, "Loop"))
  267.         {
  268.                 string sLabel = GenerateUniqueLabelName();
  269.                 pGoalPipe->PushLabel(sLabel.c_str());
  270.  
  271.                 ParseGoalOps(pGoalPipe, goalOpNode);
  272.  
  273.                 params.nValue = BRANCH_ALWAYS;
  274.                 params.str = sLabel;
  275.                 pGoalPipe->PushGoal(eGO_BRANCH, false, IGoalPipe::eGT_NOGROUP, params);
  276.                 return;
  277.         }
  278.  
  279.         if (!stricmp(szGoalOpName, "SubGoalPipe"))
  280.         {
  281.                 const char* szSubGoalPipeName;
  282.                 if (!goalOpNode->getAttr("name", &szSubGoalPipeName))
  283.                 {
  284.                         AIError("Unable to get mandatory attribute 'name' of node 'SubGoalPipe'.");
  285.                         szSubGoalPipeName = "";
  286.                 }
  287.  
  288.                 if (!gAIEnv.pPipeManager->OpenGoalPipe(szSubGoalPipeName))
  289.                 {
  290.                         AIWarning("Tried to push a goal pipe to '%s' that is not yet defined: '%s'.",
  291.                                   pGoalPipe->GetName(), szSubGoalPipeName);
  292.                 }
  293.                 pGoalPipe->PushPipe(szSubGoalPipeName, true, IGoalPipe::eGT_NOGROUP, params);
  294.  
  295.                 m_currentGrouping = IGoalPipe::eGT_NOGROUP;
  296.  
  297.                 //AILogLoading("Added call to sub-goal pipe '%s'.", szSubGoalPipeName);
  298.                 return;
  299.         }
  300.  
  301.         pGoalPipe->PushGoal(goalOpNode, m_currentGrouping);
  302.  
  303.         if (m_currentGrouping == IGoalPipe::eGT_GROUPED)
  304.         {
  305.                 m_currentGrouping = IGoalPipe::eGT_GROUPWITHPREV;
  306.         }
  307.  
  308.         //AILogLoading("Added goalop %s", szGoalOpName);
  309. }
  310.  
  311. string CGoalPipeXMLReader::GenerateUniqueLabelName()
  312. {
  313.         char szLabel[100];
  314.         cry_sprintf(szLabel, "Label%d", m_nextUniqueLabelID++);
  315.         return szLabel;
  316. }
  317.  
  318. void CGoalPipeXMLReader::ParseGoalPipe(const char* szGoalPipeName, const XmlNodeRef goalPipeNode
  319.                                        , CPipeManager::ActionToTakeWhenDuplicateFound actionToTakeWhenDuplicateFound /*= CPipeManager::ReplaceDuplicateAndReportError*/)
  320. {
  321.         CPipeManager* pPipeManager = gAIEnv.pPipeManager;
  322.  
  323.         IGoalPipe* pGoalPipe = pPipeManager->CreateGoalPipe(
  324.           szGoalPipeName, actionToTakeWhenDuplicateFound);
  325.  
  326.         if (!pGoalPipe)
  327.         {
  328.                 AIError("Could not create goal pipe '%s'.", szGoalPipeName);
  329.                 return;
  330.         }
  331.  
  332.         //AILogLoading("Created goal pipe '%s'.", szGoalPipeName);
  333.  
  334.         m_nextUniqueLabelID = 0;
  335.         m_currentGrouping = IGoalPipe::eGT_NOGROUP;
  336.  
  337.         ParseGoalOps(pGoalPipe, goalPipeNode);
  338. }
  339.  
  340. bool CGoalPipeXMLReader::CXMLAttrReader::Get(const char* szKey, int& nValue)
  341. {
  342.         for (std::vector<TRecord>::iterator it = m_dictionary.begin(), end = m_dictionary.end(); it != end; ++it)
  343.         {
  344.                 if (!stricmp(it->first, szKey))
  345.                 {
  346.                         nValue = it->second;
  347.                         return true;
  348.                 }
  349.         }
  350.  
  351.         return false;
  352. }
  353.  
downloadGoalPipeXMLReader.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