BVB Source Codes

CRYENGINE Show FactionMap.cpp Source code

Return Download CRYENGINE: download FactionMap.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 "FactionMap.h"
  5.  
  6. CFactionXmlDataSource CFactionMap::s_defaultXmlDataSource("Scripts/AI/Factions.xml");
  7.  
  8. CFactionMap::CFactionMap()
  9. {
  10.         SetDataSource(&s_defaultXmlDataSource, EDataSourceLoad::Now);
  11. }
  12.  
  13. uint32 CFactionMap::GetFactionCount() const
  14. {
  15.         return m_namesById.size();
  16. }
  17.  
  18. uint32 CFactionMap::GetMaxFactionCount() const
  19. {
  20.         return maxFactionCount;
  21. }
  22.  
  23. const char* CFactionMap::GetFactionName(const uint8 factionId) const
  24. {
  25.         FactionNamesById::const_iterator it = m_namesById.find(factionId);
  26.         if (it != m_namesById.end())
  27.         {
  28.                 return it->second.c_str();
  29.         }
  30.  
  31.         return nullptr;
  32. }
  33.  
  34. uint8 CFactionMap::GetFactionID(const char* szName) const
  35. {
  36.         FactionIdsByName::const_iterator it = m_idsByName.find(CONST_TEMP_STRING(szName));
  37.         if (it != m_idsByName.end())
  38.         {
  39.                 return it->second;
  40.         }
  41.  
  42.         return InvalidFactionID;
  43. }
  44.  
  45. void CFactionMap::Clear()
  46. {
  47.         m_namesById.clear();
  48.         m_idsByName.clear();
  49.  
  50.         for (uint32 i = 0; i < maxFactionCount; ++i)
  51.         {
  52.                 for (uint32 j = 0; j < maxFactionCount; ++j)
  53.                 {
  54.                         m_reactions[i][j] = (i != j) ? Hostile : Friendly;
  55.                 }
  56.         }
  57. }
  58.  
  59. void CFactionMap::Reload()
  60. {
  61.         Clear();
  62.  
  63.         if (m_pDataSource)
  64.         {
  65.                 if (!m_pDataSource->Load(*this))
  66.                 {
  67.                         AIWarning("[FactionMap] Failed to load factions from data source!");
  68.                 }
  69.         }
  70. }
  71.  
  72. uint8 CFactionMap::CreateOrUpdateFaction(const char* szName, uint32 reactionsCount, const uint8* pReactions)
  73. {
  74.         if (szName && szName[0])
  75.         {
  76.                 std::pair<FactionNamesById::iterator, bool> namesByIdResult;
  77.                 std::pair<FactionIdsByName::iterator, bool> idByNamesResult;
  78.  
  79.                 uint8 factionId = GetFactionID(szName);
  80.                 if (factionId == InvalidFactionID)
  81.                 {
  82.                         if (m_namesById.size() < maxFactionCount)
  83.                         {
  84.                                 factionId = static_cast<uint8>(m_namesById.size());
  85.                                 namesByIdResult = m_namesById.emplace(factionId, szName);
  86.                                 idByNamesResult = m_idsByName.emplace(szName, factionId);
  87.  
  88.                                 if (!namesByIdResult.second || !idByNamesResult.second)
  89.                                 {
  90.                                         AIError("[FactionMap] CreateOrUpdateFaction(...) failed. Reason: Failed to insert faction!");
  91.  
  92.                                         if (namesByIdResult.second) m_namesById.erase(namesByIdResult.first);
  93.                                         if (idByNamesResult.second) m_idsByName.erase(idByNamesResult.first);
  94.  
  95.                                         return InvalidFactionID;
  96.                                 }
  97.                         }
  98.                         else
  99.                         {
  100.                                 AIError("[FactionMap] CreateOrUpdateFaction(...) failed. Reason: Max faction count reached!");
  101.                                 return InvalidFactionID;
  102.                         }
  103.                 }
  104.  
  105.                 if (reactionsCount && pReactions)
  106.                 {
  107.                         const size_t bytesToCopy = std::min(reactionsCount, static_cast<uint32>(maxFactionCount));
  108.  
  109.                         // Let the function fail in case of an overlapping copy.
  110.                         const size_t dstMin = reinterpret_cast<size_t>(m_reactions[factionId]);
  111.                         const size_t dstMax = dstMin + bytesToCopy;
  112.                         const size_t srcMin = reinterpret_cast<size_t>(pReactions);
  113.                         const size_t srcMax = srcMin + bytesToCopy;
  114.  
  115.                         CRY_ASSERT(dstMin >= srcMax || dstMax <= srcMin);
  116.                         if (dstMin >= srcMax || dstMax <= srcMin)
  117.                         {
  118.                                 memcpy(m_reactions[factionId], pReactions, sizeof(uint8) * bytesToCopy);
  119.                                 m_reactions[factionId][factionId] = Friendly;
  120.  
  121.                                 return factionId;
  122.                         }
  123.                         else
  124.                         {
  125.                                 AIError("[FactionMap] CreateOrUpdateFaction(...) failed. Reason: Overlapping copy detected!");
  126.  
  127.                                 if (namesByIdResult.second) m_namesById.erase(namesByIdResult.first);
  128.                                 if (idByNamesResult.second) m_idsByName.erase(idByNamesResult.first);
  129.                         }
  130.                 }
  131.                 else
  132.                 {
  133.                         AIWarning("[FactionMap] CreateOrUpdateFaction(...) called with invalid reaction data. Parameters: 'reactionsCount' = '%d', 'pReactions' = '0x%p'", reactionsCount, pReactions);
  134.                 }
  135.         }
  136.  
  137.         return InvalidFactionID;
  138. }
  139.  
  140. void CFactionMap::RemoveFaction(const char* szName)
  141. {
  142.         if (gEnv->IsEditor())
  143.         {
  144.                 const uint8 removeFactionId = GetFactionID(szName);
  145.                 if (removeFactionId != InvalidFactionID)
  146.                 {
  147.                         uint8 oldReactions[maxFactionCount][maxFactionCount];
  148.                         memcpy(oldReactions, m_reactions, sizeof(oldReactions));
  149.  
  150.                         FactionNamesById oldNamesById;
  151.                         oldNamesById.swap(m_namesById);
  152.                         m_idsByName.clear();
  153.  
  154.                         const size_t bytesFirstPart = sizeof(uint8) * (removeFactionId != 0 ? removeFactionId : maxFactionCount);
  155.                         const size_t bytesSecondPart = sizeof(uint8) * (maxFactionCount - 1 - removeFactionId);
  156.                         for (const FactionNamesById::value_type& kvPair : oldNamesById)
  157.                         {
  158.                                 if (kvPair.first != removeFactionId)
  159.                                 {
  160.                                         const uint8 newId = static_cast<uint8>(m_namesById.size());
  161.                                         m_namesById.emplace(newId, kvPair.second.c_str());
  162.                                         m_idsByName.emplace(kvPair.second.c_str(), newId);
  163.  
  164.                                         memcpy(m_reactions[newId], oldReactions[kvPair.first], bytesFirstPart);
  165.                                         if (removeFactionId != 0)
  166.                                         {
  167.                                                 memcpy(&m_reactions[newId][removeFactionId], &oldReactions[kvPair.first][removeFactionId + 1], bytesSecondPart);
  168.                                         }
  169.                                 }
  170.                         }
  171.                 }
  172.         }
  173.         else
  174.         {
  175.                 AIWarning("[FactionMap] RemoveFaction(...) is only allowed in editor mode.");
  176.         }
  177. }
  178.  
  179. void CFactionMap::SetReaction(uint8 factionOne, uint8 factionTwo, IFactionMap::ReactionType reaction)
  180. {
  181.         if ((factionOne < maxFactionCount) && (factionTwo < maxFactionCount))
  182.         {
  183.                 m_reactions[factionOne][factionTwo] = reaction;
  184.  
  185.                 // TODO: We should use callbacks instead.
  186.                 AIObjects::iterator it = GetAISystem()->m_mapFaction.find(factionOne);
  187.                 const AIObjects::iterator end = GetAISystem()->m_mapFaction.end();
  188.  
  189.                 for (; it != end; ++it)
  190.                 {
  191.                         if (it->first == factionOne)
  192.                         {
  193.                                 if (CAIObject* pObject = it->second.GetAIObject())
  194.                                 {
  195.                                         if (CAIActor* pAIActor = pObject->CastToCAIActor())
  196.                                         {
  197.                                                 pAIActor->ReactionChanged(factionTwo, reaction);
  198.                                         }
  199.                                 }
  200.                         }
  201.                         else
  202.                         {
  203.                                 break;
  204.                         }
  205.                 }
  206.                 // ~TODO
  207.         }
  208. }
  209.  
  210. IFactionMap::ReactionType CFactionMap::GetReaction(const uint8 factionOne, const uint8 factionTwo) const
  211. {
  212.         if ((factionOne < maxFactionCount) && (factionTwo < maxFactionCount))
  213.         {
  214.                 return static_cast<IFactionMap::ReactionType>(m_reactions[factionOne][factionTwo]);
  215.         }
  216.  
  217.         if (factionOne != InvalidFactionID && factionTwo != InvalidFactionID)
  218.         {
  219.                 return Neutral;
  220.         }
  221.  
  222.         return Hostile;
  223. }
  224.  
  225. void CFactionMap::Serialize(TSerialize ser)
  226. {
  227.         ser.BeginGroup("FactionMap");
  228.  
  229.         // find highest faction id
  230.         uint32 highestId = 0;
  231.  
  232.         if (ser.IsWriting())
  233.         {
  234.                 FactionIdsByName::iterator it = m_idsByName.begin();
  235.                 FactionIdsByName::iterator end = m_idsByName.end();
  236.  
  237.                 for (; it != end; ++it)
  238.                 {
  239.                         if (it->second > highestId)
  240.                                 highestId = it->second;
  241.                 }
  242.         }
  243.  
  244.         ser.Value("SerializedFactionCount", highestId);
  245.  
  246.         stack_string nameFormatter;
  247.         for (size_t i = 0; i < highestId; ++i)
  248.         {
  249.                 for (size_t j = 0; j < highestId; ++j)
  250.                 {
  251.                         nameFormatter.Format("Reaction_%" PRISIZE_T "_to_%" PRISIZE_T, i, j);
  252.                         ser.Value(nameFormatter.c_str(), m_reactions[i][j]);
  253.                 }
  254.         }
  255.  
  256.         ser.EndGroup();
  257. }
  258.  
  259. bool CFactionMap::GetReactionType(const char* szReactionName, ReactionType* pReactionType)
  260. {
  261.         if (!stricmp(szReactionName, "Friendly"))
  262.         {
  263.                 if (pReactionType)
  264.                 {
  265.                         *pReactionType = Friendly;
  266.                 }
  267.         }
  268.         else if (!stricmp(szReactionName, "Hostile"))
  269.         {
  270.                 if (pReactionType)
  271.                 {
  272.                         *pReactionType = Hostile;
  273.                 }
  274.         }
  275.         else if (!stricmp(szReactionName, "Neutral"))
  276.         {
  277.                 if (pReactionType)
  278.                 {
  279.                         *pReactionType = Neutral;
  280.                 }
  281.         }
  282.         else
  283.         {
  284.                 return false;
  285.         }
  286.  
  287.         return true;
  288. }
  289.  
  290. void CFactionMap::SetDataSource(IFactionDataSource* pDataSource, EDataSourceLoad bLoad)
  291. {
  292.         Clear();
  293.         m_pDataSource = pDataSource;
  294.         if (m_pDataSource && bLoad == EDataSourceLoad::Now)
  295.         {
  296.                 if (!m_pDataSource->Load(*this))
  297.                 {
  298.                         AIWarning("[FactionMap] Failed to load factions from data source!");
  299.                 }
  300.         }
  301. }
  302.  
  303. void CFactionMap::RemoveDataSource(IFactionDataSource* pDataSource)
  304. {
  305.         if (m_pDataSource == pDataSource)
  306.         {
  307.                 Clear();
  308.                 m_pDataSource = nullptr;
  309.         }
  310. }
  311.  
  312. bool CFactionXmlDataSource::Load(IFactionMap& factionMap)
  313. {
  314.         if (!gEnv->pCryPak->IsFileExist(m_fileName.c_str()))
  315.         {
  316.                 return false;
  317.         }
  318.  
  319.         XmlNodeRef rootNode = GetISystem()->LoadXmlFromFile(m_fileName.c_str());
  320.         if (!rootNode)
  321.         {
  322.                 AIWarning("Failed to open faction XML file '%s'.", m_fileName.c_str());
  323.                 return false;
  324.         }
  325.  
  326.         uint8 reactions[CFactionMap::maxFactionCount][CFactionMap::maxFactionCount];
  327.  
  328.         const char* szRootName = rootNode->getTag();
  329.         if (!stricmp(szRootName, "Factions"))
  330.         {
  331.                 // Create factions with default reactions
  332.                 const int32 factionNodeCount = rootNode->getChildCount();
  333.                 for (int32 factionIdx = 0; factionIdx < factionNodeCount; ++factionIdx)
  334.                 {
  335.                         const XmlNodeRef factionNode = rootNode->getChild(factionIdx);
  336.  
  337.                         if (!stricmp(factionNode->getTag(), "Faction"))
  338.                         {
  339.                                 if (factionIdx >= CFactionMap::maxFactionCount)
  340.                                 {
  341.                                         AIWarning("Maximum number of allowed factions reached in file '%s' at line '%d'!", m_fileName.c_str(), factionNode->getLine());
  342.                                         return false;
  343.                                 }
  344.  
  345.                                 const char* szFactionName = nullptr;
  346.                                 if (!factionNode->getAttr("name", &szFactionName) || szFactionName == nullptr || szFactionName[0] == '\0')
  347.                                 {
  348.                                         AIWarning("Missing or empty 'name' attribute for 'Faction' tag in file '%s' at line %d...", m_fileName.c_str(), factionNode->getLine());
  349.                                         return false;
  350.                                 }
  351.  
  352.                                 const uint8 factionId = factionMap.GetFactionID(szFactionName);
  353.                                 if (factionId != CFactionMap::InvalidFactionID)
  354.                                 {
  355.                                         AIWarning("Duplicate faction '%s' in file '%s' at line %d...", szFactionName, m_fileName.c_str(), factionNode->getLine());
  356.                                         return false;
  357.                                 }
  358.  
  359.                                 CFactionMap::ReactionType defaultReactionType = CFactionMap::Hostile;
  360.  
  361.                                 const char* szDefaultReaction = nullptr;
  362.                                 if (factionNode->getAttr("default", &szDefaultReaction) && szDefaultReaction && szDefaultReaction[0])
  363.                                 {
  364.                                         if (!CFactionMap::GetReactionType(szDefaultReaction, &defaultReactionType))
  365.                                         {
  366.                                                 AIWarning("Invalid default reaction '%s' in file '%s' at line '%d'...", szDefaultReaction, m_fileName.c_str(), factionNode->getLine());
  367.                                                 return false;
  368.                                         }
  369.                                 }
  370.                                 memset(reactions[factionIdx], defaultReactionType, sizeof(reactions[factionIdx]));
  371.  
  372.                                 factionMap.CreateOrUpdateFaction(szFactionName, CFactionMap::maxFactionCount, reactions[factionIdx]);
  373.                         }
  374.                         else
  375.                         {
  376.                                 AIWarning("Unexpected tag '%s' in file '%s' at line %d...", factionNode->getTag(), m_fileName.c_str(), factionNode->getLine());
  377.                                 return false;
  378.                         }
  379.                 }
  380.  
  381.                 // Update factions reactions
  382.                 for (int32 factionIdx = 0; factionIdx < factionNodeCount; ++factionIdx)
  383.                 {
  384.                         const XmlNodeRef factionNode = rootNode->getChild(factionIdx);
  385.  
  386.                         const char* szFactionName;
  387.                         factionNode->getAttr("name", &szFactionName);
  388.                         const uint8 factionId = factionMap.GetFactionID(szFactionName);
  389.  
  390.                         const int32 reactionNodeCount = factionNode->getChildCount();
  391.                         for (int32 reactionIdx = 0; reactionIdx < reactionNodeCount; ++reactionIdx)
  392.                         {
  393.                                 XmlNodeRef reactionNode = factionNode->getChild(reactionIdx);
  394.                                 if (!stricmp(reactionNode->getTag(), "Reaction"))
  395.                                 {
  396.                                         const char* szReactionOnFaction = nullptr;
  397.                                         if (!reactionNode->getAttr("faction", &szReactionOnFaction) || szReactionOnFaction == nullptr || szReactionOnFaction[0] == '\0')
  398.                                         {
  399.                                                 AIWarning("Missing or empty 'faction' attribute for 'Reaction' tag in file '%s' at line %d...", m_fileName.c_str(), reactionNode->getLine());
  400.                                                 return false;
  401.                                         }
  402.  
  403.                                         const uint8 reactionOnfactionId = factionMap.GetFactionID(szReactionOnFaction);
  404.                                         if (reactionOnfactionId == CFactionMap::InvalidFactionID)
  405.                                         {
  406.                                                 AIWarning("Attribute 'faction' for 'Reaction' tag in file '%s' at line %d defines an unknown faction...", m_fileName.c_str(), reactionNode->getLine());
  407.                                                 return false;
  408.                                         }
  409.  
  410.                                         const char* szReaction = nullptr;
  411.                                         if (!reactionNode->getAttr("reaction", &szReaction) || szReaction == nullptr || szReaction[0] == '\0')
  412.                                         {
  413.                                                 AIWarning("Missing or empty 'reaction' attribute for 'Reaction' tag in file '%s' at line %d...", m_fileName.c_str(), reactionNode->getLine());
  414.                                                 return false;
  415.                                         }
  416.  
  417.                                         CFactionMap::ReactionType reactionType = CFactionMap::Neutral;
  418.                                         if (!CFactionMap::GetReactionType(szReaction, &reactionType))
  419.                                         {
  420.                                                 AIWarning("Invalid reaction '%s' in file '%s' at line '%d'...", szReaction, m_fileName.c_str(), reactionNode->getLine());
  421.                                                 //return false;
  422.                                         }
  423.  
  424.                                         reactions[factionId][reactionOnfactionId] = static_cast<uint8>(reactionType);
  425.                                 }
  426.                                 else
  427.                                 {
  428.                                         AIWarning("Unexpected tag '%s' in file '%s' at line %d...", reactionNode->getTag(), m_fileName.c_str(), reactionNode->getLine());
  429.                                         return false;
  430.                                 }
  431.                         }
  432.  
  433.                         factionMap.CreateOrUpdateFaction(szFactionName, CFactionMap::maxFactionCount, reactions[factionId]);
  434.                 }
  435.         }
  436.         else
  437.         {
  438.                 AIWarning("Unexpected tag '%s' in file '%s' at line %d...", szRootName, m_fileName.c_str(), rootNode->getLine());
  439.                 return false;
  440.         }
  441.  
  442.         return true;
  443. }
  444.  
downloadFactionMap.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