void CCmpPathfinder::Init(const CParamNode& UNUSED(paramNode)) { m_MapSize = 0; m_Grid = NULL; m_TerrainOnlyGrid = NULL; m_ObstructionsDirty.Clean(); m_PreserveUpdateInformations = false; m_NextAsyncTicket = 1; m_DebugOverlay = false; m_AtlasOverlay = NULL; m_SameTurnMovesCount = 0; // Register Relax NG validator CXeromyces::AddValidator(g_VFS, "pathfinder", "simulation/data/pathfinder.rng"); // Since this is used as a system component (not loaded from an entity template), // we can't use the real paramNode (it won't get handled properly when deserializing), // so load the data from a special XML file. CParamNode externalParamNode; CParamNode::LoadXML(externalParamNode, L"simulation/data/pathfinder.xml", "pathfinder"); // Previously all move commands during a turn were // queued up and processed asynchronously at the start // of the next turn. Now we are processing queued up // events several times duing the turn. This improves // responsiveness and units move more smoothly especially. // when in formation. There is still a call at the // beginning of a turn to process all outstanding moves - // this will handle any moves above the MaxSameTurnMoves // threshold. // // TODO - The moves processed at the beginning of the // turn do not count against the maximum moves per turn // currently. The thinking is that this will eventually // happen in another thread. Either way this probably // will require some adjustment and rethinking. const CParamNode pathingSettings = externalParamNode.GetChild("Pathfinder"); m_MaxSameTurnMoves = (u16)pathingSettings.GetChild("MaxSameTurnMoves").ToInt(); const CParamNode::ChildrenMap& passClasses = externalParamNode.GetChild("Pathfinder").GetChild("PassabilityClasses").GetChildren(); for (CParamNode::ChildrenMap::const_iterator it = passClasses.begin(); it != passClasses.end(); ++it) { std::string name = it->first; ENSURE((int)m_PassClasses.size() <= PASS_CLASS_BITS); pass_class_t mask = PASS_CLASS_MASK_FROM_INDEX(m_PassClasses.size()); m_PassClasses.push_back(PathfinderPassability(mask, it->second)); m_PassClassMasks[name] = mask; } }
void CCmpPathfinder::Init(const CParamNode& UNUSED(paramNode)) { m_MapSize = 0; m_Grid = NULL; m_ObstructionGrid = NULL; m_TerrainDirty = true; m_NextAsyncTicket = 1; m_DebugOverlay = NULL; m_DebugGrid = NULL; m_DebugPath = NULL; m_SameTurnMovesCount = 0; // Since this is used as a system component (not loaded from an entity template), // we can't use the real paramNode (it won't get handled properly when deserializing), // so load the data from a special XML file. CParamNode externalParamNode; CParamNode::LoadXML(externalParamNode, L"simulation/data/pathfinder.xml"); // Previously all move commands during a turn were // queued up and processed asynchronously at the start // of the next turn. Now we are processing queued up // events several times duing the turn. This improves // responsiveness and units move more smoothly especially. // when in formation. There is still a call at the // beginning of a turn to process all outstanding moves - // this will handle any moves above the MaxSameTurnMoves // threshold. // // TODO - The moves processed at the beginning of the // turn do not count against the maximum moves per turn // currently. The thinking is that this will eventually // happen in another thread. Either way this probably // will require some adjustment and rethinking. const CParamNode pathingSettings = externalParamNode.GetChild("Pathfinder"); m_MaxSameTurnMoves = (u16)pathingSettings.GetChild("MaxSameTurnMoves").ToInt(); const CParamNode::ChildrenMap& passClasses = externalParamNode.GetChild("Pathfinder").GetChild("PassabilityClasses").GetChildren(); for (CParamNode::ChildrenMap::const_iterator it = passClasses.begin(); it != passClasses.end(); ++it) { std::string name = it->first; ENSURE((int)m_PassClasses.size() <= PASS_CLASS_BITS); pass_class_t mask = (pass_class_t)(1u << (m_PassClasses.size() + 2)); m_PassClasses.push_back(PathfinderPassability(mask, it->second)); m_PassClassMasks[name] = mask; } const CParamNode::ChildrenMap& moveClasses = externalParamNode.GetChild("Pathfinder").GetChild("MovementClasses").GetChildren(); // First find the set of unit classes used by any terrain classes, // and assign unique tags to terrain classes std::set<std::string> unitClassNames; unitClassNames.insert("default"); // must always have costs for default { size_t i = 0; for (CParamNode::ChildrenMap::const_iterator it = moveClasses.begin(); it != moveClasses.end(); ++it) { std::string terrainClassName = it->first; m_TerrainCostClassTags[terrainClassName] = (cost_class_t)i; ++i; const CParamNode::ChildrenMap& unitClasses = it->second.GetChild("UnitClasses").GetChildren(); for (CParamNode::ChildrenMap::const_iterator uit = unitClasses.begin(); uit != unitClasses.end(); ++uit) unitClassNames.insert(uit->first); } } // For each terrain class, set the costs for every unit class, // and assign unique tags to unit classes { size_t i = 0; for (std::set<std::string>::const_iterator nit = unitClassNames.begin(); nit != unitClassNames.end(); ++nit) { m_UnitCostClassTags[*nit] = (cost_class_t)i; ++i; std::vector<u32> costs; std::vector<fixed> speeds; for (CParamNode::ChildrenMap::const_iterator it = moveClasses.begin(); it != moveClasses.end(); ++it) { // Default to the general costs for this terrain class fixed cost = it->second.GetChild("@Cost").ToFixed(); fixed speed = it->second.GetChild("@Speed").ToFixed(); // Check for specific cost overrides for this unit class const CParamNode& unitClass = it->second.GetChild("UnitClasses").GetChild(nit->c_str()); if (unitClass.IsOk()) { cost = unitClass.GetChild("@Cost").ToFixed(); speed = unitClass.GetChild("@Speed").ToFixed(); } costs.push_back((cost * DEFAULT_MOVE_COST).ToInt_RoundToZero()); speeds.push_back(speed); } m_MoveCosts.push_back(costs); m_MoveSpeeds.push_back(speeds); } } }