diff --git a/rts/Sim/Misc/ModInfo.cpp b/rts/Sim/Misc/ModInfo.cpp index 2a4e515ce6..81315eccfe 100644 --- a/rts/Sim/Misc/ModInfo.cpp +++ b/rts/Sim/Misc/ModInfo.cpp @@ -24,6 +24,7 @@ void CModInfo::ResetState() description.clear(); { + preferShortestPath = false; allowDirectionalPathing = true; allowAircraftToLeaveMap = true; allowAircraftToHitGround = true; @@ -182,6 +183,7 @@ void CModInfo::Init(const std::string& modFileName) // movement const LuaTable& movementTbl = root.SubTable("movement"); + preferShortestPath = movementTbl.GetBool("preferShortestPath", preferShortestPath); allowDirectionalPathing = movementTbl.GetBool("allowDirectionalPathing", allowDirectionalPathing); allowAircraftToLeaveMap = movementTbl.GetBool("allowAirPlanesToLeaveMap", allowAircraftToLeaveMap); allowAircraftToHitGround = movementTbl.GetBool("allowAircraftToHitGround", allowAircraftToHitGround); diff --git a/rts/Sim/Misc/ModInfo.h b/rts/Sim/Misc/ModInfo.h index 2fdbe6568f..d2a6651f26 100644 --- a/rts/Sim/Misc/ModInfo.h +++ b/rts/Sim/Misc/ModInfo.h @@ -41,6 +41,7 @@ class CModInfo std::string description; // Movement behaviour + bool preferShortestPath; //< if pathing system supports it, use shortest route instead of fastest route bool allowDirectionalPathing; //< determines if ground speed going downhill != going uphill bool allowAircraftToLeaveMap; //< determines if gunships are allowed to leave map boundaries bool allowAircraftToHitGround; //< determines if aircraft (both types) can collide with terrain diff --git a/rts/Sim/MoveTypes/MoveDefHandler.cpp b/rts/Sim/MoveTypes/MoveDefHandler.cpp index 6c568aeb1c..cf925a109a 100644 --- a/rts/Sim/MoveTypes/MoveDefHandler.cpp +++ b/rts/Sim/MoveTypes/MoveDefHandler.cpp @@ -154,6 +154,7 @@ void MoveDefHandler::PostSimInit() { // capabilities of the pathing system. std::for_each(moveDefs.begin(), moveDefs.end(), [](MoveDef& md){ md.allowDirectionalPathing &= pathManager->AllowDirectionalPathing(); + md.preferShortestPath &= pathManager->AllowShortestPath(); }); } @@ -319,7 +320,8 @@ MoveDef::MoveDef(const LuaTable& moveDefTable): MoveDef() { height = std::max(1, moveDefTable.GetInt("height", defaultHeight)); - allowDirectionalPathing = moveDefTable.GetBool("allowDirectionalPathing", allowDirectionalPathing); + allowDirectionalPathing = moveDefTable.GetBool("allowDirectionalPathing", allowDirectionalPathing); + preferShortestPath = moveDefTable.GetBool("preferShortestPath", preferShortestPath); } bool MoveDef::DoRawSearch( diff --git a/rts/Sim/MoveTypes/MoveDefHandler.h b/rts/Sim/MoveTypes/MoveDefHandler.h index 365cfb6814..2d7e8a75d4 100644 --- a/rts/Sim/MoveTypes/MoveDefHandler.h +++ b/rts/Sim/MoveTypes/MoveDefHandler.h @@ -182,6 +182,7 @@ struct MoveDef { bool allowTerrainCollisions = true; bool allowDirectionalPathing = true; bool allowRawMovement = false; + bool preferShortestPath = true; /// do we leave heat and avoid any left by others? bool heatMapping = true; diff --git a/rts/Sim/Path/IPathManager.h b/rts/Sim/Path/IPathManager.h index b5407833aa..a60ce34c0d 100644 --- a/rts/Sim/Path/IPathManager.h +++ b/rts/Sim/Path/IPathManager.h @@ -27,6 +27,7 @@ class IPathManager { virtual std::int64_t PostFinalizeRefresh() { return 0; } virtual bool AllowDirectionalPathing() { return false; } + virtual bool AllowShortestPath() { return false; } /** * returns if a path was changed after RequestPath returned its pathID diff --git a/rts/Sim/Path/QTPFS/Node.cpp b/rts/Sim/Path/QTPFS/Node.cpp index 6e3adc69c7..f6ddbbfcbf 100644 --- a/rts/Sim/Path/QTPFS/Node.cpp +++ b/rts/Sim/Path/QTPFS/Node.cpp @@ -549,7 +549,7 @@ bool QTPFS::QTNode::UpdateMoveCost( assert(speedModSum >= 0.0f); float speedModAvg = speedModSum / area(); - moveCostAvg = (speedModAvg <= 0.001f) ? QTPFS_POSITIVE_INFINITY : (1.0f / speedModAvg); + moveCostAvg = (speedModAvg <= 0.001f) ? QTPFS_POSITIVE_INFINITY : (nl.UseShortestPath() ? 1.f : (1.f / speedModAvg)); // no node can have ZERO traversal cost assert(moveCostAvg > 0.0f); @@ -598,6 +598,7 @@ bool QTPFS::QTNode::UpdateMoveCost( needSplit |= (AllSquaresImpassable() && xsize() > 16); // TODO: magic number for size of damage quads wantSplit &= (xsize() > 16); // try not to split below 16 if possible. + wantSplit &= !(nl.UseShortestPath()); return (wantSplit || needSplit); } diff --git a/rts/Sim/Path/QTPFS/NodeLayer.cpp b/rts/Sim/Path/QTPFS/NodeLayer.cpp index 08cd671ae3..c4ab015ea1 100644 --- a/rts/Sim/Path/QTPFS/NodeLayer.cpp +++ b/rts/Sim/Path/QTPFS/NodeLayer.cpp @@ -72,6 +72,9 @@ void QTPFS::NodeLayer::Init(unsigned int layerNum) { curSpeedMods.resize(xsize * zsize, 0); curSpeedBins.resize(xsize * zsize, -1); + + MoveDef* md = moveDefHandler.GetMoveDefByPathType(layerNum); + useShortestPath = md->preferShortestPath; } void QTPFS::NodeLayer::Clear() { diff --git a/rts/Sim/Path/QTPFS/NodeLayer.h b/rts/Sim/Path/QTPFS/NodeLayer.h index a7d64717b5..efbcb546ee 100644 --- a/rts/Sim/Path/QTPFS/NodeLayer.h +++ b/rts/Sim/Path/QTPFS/NodeLayer.h @@ -163,6 +163,8 @@ namespace QTPFS { INode* GetNearestNodeInArea(const SRectangle& areaToSearch, int2 referencePoint, std::vector& openNodes); INode* GetNodeThatEncasesPowerOfTwoArea(const SRectangle& areaToEncase); + bool UseShortestPath() { return useShortestPath; } + private: std::vector poolNodes[16]; std::vector nodeIndcs; @@ -220,6 +222,7 @@ namespace QTPFS { float maxRelSpeedMod = 0.0f; // TODO: Remove these? float avgRelSpeedMod = 0.0f; + bool useShortestPath = false; }; } diff --git a/rts/Sim/Path/QTPFS/PathManager.h b/rts/Sim/Path/QTPFS/PathManager.h index 4a878424b0..de7babcd8a 100644 --- a/rts/Sim/Path/QTPFS/PathManager.h +++ b/rts/Sim/Path/QTPFS/PathManager.h @@ -5,6 +5,7 @@ #include +#include "Sim/Misc/ModInfo.h" #include "Sim/Path/IPathManager.h" #include "NodeLayer.h" #include "PathCache.h" @@ -47,6 +48,8 @@ namespace QTPFS { bool PathUpdated(unsigned int pathID) override; void ClearPathUpdated(unsigned int pathID) override; + bool AllowShortestPath() override { return modInfo.preferShortestPath; } + void TerrainChange(unsigned int x1, unsigned int z1, unsigned int x2, unsigned int z2, unsigned int type) override; void Update() override; void UpdatePath(const CSolidObject* owner, unsigned int pathID) override;