Ticket #1468: pathfinderDistance.patch
File pathfinderDistance.patch, 13.6 KB (added by , 8 years ago) |
---|
-
binaries/data/mods/public/simulation/components/UnitAI.js
2390 2390 // Nothing else to gather - if we're carrying anything then we should 2391 2391 // drop it off, and if not then we might as well head to the dropsite 2392 2392 // anyway because that's a nice enough place to congregate and idle 2393 2394 2393 var nearby = this.FindNearestDropsite(resourceType.generic); 2395 2394 if (nearby) 2396 2395 { … … 4007 4006 }; 4008 4007 4009 4008 /** 4009 * Returns the nearest element in terms of total path length 4010 * when given an array of entities 4011 */ 4012 UnitAI.prototype.FindNearest = function(nearby) 4013 { 4014 if (nearby.length == 0) 4015 return undefined; 4016 4017 let nearest = nearby[0]; 4018 let cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion) 4019 if (!cmpUnitMotion) 4020 return nearest; 4021 let cmpPosition = Engine.QueryInterface(nearest, IID_Position); 4022 if (!cmpPosition || !cmpPosition.IsInWorld()) 4023 return nearest; 4024 let pos = cmpPosition.GetPosition2D(); 4025 let minCost = cmpUnitMotion.GetPathCost(pos.x,pos.y); 4026 4027 let len = nearby.length 4028 for(let i=1; i<len; i++) 4029 { 4030 cmpPosition = Engine.QueryInterface(nearby[i], IID_Position); 4031 if (!cmpPosition || !cmpPosition.IsInWorld()) 4032 continue; 4033 pos = cmpPosition.GetPosition2D(); 4034 let cost = cmpUnitMotion.GetPathCost(pos.x,pos.y); 4035 if (cost < minCost) 4036 { 4037 nearest = nearby[i]; 4038 minCost = cost; 4039 } 4040 } 4041 return nearest; 4042 } 4043 4044 /** 4010 4045 * Returns the entity ID of the nearest resource supply where the given 4011 4046 * filter returns true, or undefined if none can be found. 4012 4047 * if target if given, the nearest is computed versus this target position. … … 4038 4073 entity = target; 4039 4074 } 4040 4075 var nearby = cmpRangeManager.ExecuteQuery(entity, 0, range, players, IID_ResourceSupply); 4041 return nearby.find(ent => {4076 nearby = nearby.filter(ent => { 4042 4077 if (!this.CanGather(ent)) 4043 4078 return false; 4044 4079 var cmpResourceSupply = Engine.QueryInterface(ent, IID_ResourceSupply); … … 4052 4087 4053 4088 return amount > 0 && cmpResourceSupply.IsAvailable(owner, this.entity) && filter(ent, type, template); 4054 4089 }); 4090 return this.FindNearest(nearby); 4055 4091 }; 4056 4092 4057 4093 /** … … 4060 4096 */ 4061 4097 UnitAI.prototype.FindNearestDropsite = function(genericType) 4062 4098 { 4063 varcmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);4099 let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); 4064 4100 if (!cmpOwnership || cmpOwnership.GetOwner() == -1) 4065 4101 return undefined; 4066 4102 4067 4103 // Find dropsites owned by this unit's player 4068 varplayers = [cmpOwnership.GetOwner()];4104 let players = [cmpOwnership.GetOwner()]; 4069 4105 4070 varcmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);4071 varnearby = cmpRangeManager.ExecuteQuery(this.entity, 0, -1, players, IID_ResourceDropsite);4106 let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); 4107 let nearby = cmpRangeManager.ExecuteQuery(this.entity, 0, -1, players, IID_ResourceDropsite); 4072 4108 4073 4109 // Ships are unable to reach land dropsites and shouldn't attempt to do so. 4074 varexcludeLand = Engine.QueryInterface(this.entity, IID_Identity).HasClass("Ship");4110 let excludeLand = Engine.QueryInterface(this.entity, IID_Identity).HasClass("Ship"); 4075 4111 if (excludeLand) 4076 4112 nearby = nearby.filter(e => Engine.QueryInterface(e, IID_Identity).HasClass("Naval")); 4077 4113 4078 return nearby.find(ent => Engine.QueryInterface(ent, IID_ResourceDropsite).AcceptsType(genericType)); 4114 nearby = nearby.filter(ent => Engine.QueryInterface(ent, IID_ResourceDropsite).AcceptsType(genericType)); 4115 return this.FindNearest(nearby); 4079 4116 }; 4080 4117 4081 4118 /** … … 4099 4136 // Skip foundations that are already complete. (This matters since 4100 4137 // we process the ConstructionFinished message before the foundation 4101 4138 // we're working on has been deleted.) 4102 return nearby.find(ent => !Engine.QueryInterface(ent, IID_Foundation).IsFinished()); 4139 nearby = nearby.filter(ent => !Engine.QueryInterface(ent, IID_Foundation).IsFinished()); 4140 return this.FindNearest(nearby); 4141 4103 4142 }; 4104 4143 4105 4144 /** … … 4120 4159 var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); 4121 4160 var nearby = cmpRangeManager.ExecuteQuery(this.entity, 0, range, players, IID_GarrisonHolder); 4122 4161 4123 return nearby.find(ent => {4162 nearby = nearby.filter(ent => { 4124 4163 // We only want to garrison in buildings, not in moving units like ships,... 4125 4164 if (Engine.QueryInterface(ent, IID_UnitAI)) 4126 4165 return false; … … 4128 4167 var cmpGarrisonHolder = Engine.QueryInterface(ent, IID_GarrisonHolder); 4129 4168 return cmpGarrisonHolder.AllowedToGarrison(this.entity) && !cmpGarrisonHolder.IsFull(); 4130 4169 }); 4170 return this.FindNearest(nearby); 4131 4171 }; 4132 4172 4133 4173 /** … … 4224 4264 var cmpVisual = Engine.QueryInterface(this.entity, IID_Visual); 4225 4265 if (!cmpVisual) 4226 4266 return; 4227 4267 4228 4268 cmpVisual.SetAnimationSyncRepeat(repeattime); 4229 4269 cmpVisual.SetAnimationSyncOffset(actiontime); 4230 4270 }; -
source/simulation2/components/CCmpPathfinder_Common.h
181 181 m_LongPathfinder.ComputePath(x0, z0, goal, passClass, ret); 182 182 } 183 183 184 virtual void ComputePathCost(entity_pos_t x0, entity_pos_t z0, const PathGoal& goal, pass_class_t passClass, u32& ret) 185 { 186 m_LongPathfinder.ComputePathCost(x0, z0, goal, passClass, ret); 187 } 188 184 189 virtual u32 ComputePathAsync(entity_pos_t x0, entity_pos_t z0, const PathGoal& goal, pass_class_t passClass, entity_id_t notify); 185 190 186 191 virtual void ComputeShortPath(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t clearance, entity_pos_t range, const PathGoal& goal, pass_class_t passClass, WaypointPath& ret); -
source/simulation2/components/CCmpUnitMotion.cpp
523 523 virtual bool MoveToTargetRange(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange); 524 524 virtual bool IsInTargetRange(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange); 525 525 virtual void MoveToFormationOffset(entity_id_t target, entity_pos_t x, entity_pos_t z); 526 virtual u32 GetPathCost(entity_pos_t x, entity_pos_t z); 526 527 527 528 virtual void FaceTowardsPoint(entity_pos_t x, entity_pos_t z); 528 529 … … 1396 1397 } 1397 1398 } 1398 1399 1400 u32 CCmpUnitMotion::GetPathCost(entity_pos_t x, entity_pos_t z) 1401 { 1402 CFixedVector2D from; 1403 PathGoal goal; 1404 CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity()); 1405 if (!cmpPathfinder) 1406 return -1; 1407 1408 CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle()); 1409 if (!cmpPosition || !cmpPosition->IsInWorld()) 1410 return -1; 1411 1412 goal.x = x; 1413 goal.z = z; 1414 goal.type = PathGoal::POINT; 1415 from = cmpPosition->GetPosition2D(); 1416 1417 u32 cost; 1418 WaypointPath path; 1419 cmpPathfinder->ComputePathCost(from.X, from.Y, goal, m_PassClass, cost); 1420 return cost; 1421 } 1422 1399 1423 void CCmpUnitMotion::RequestLongPath(const CFixedVector2D& from, const PathGoal& goal) 1400 1424 { 1401 1425 CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity()); -
source/simulation2/components/ICmpPathfinder.h
96 96 virtual void ComputePath(entity_pos_t x0, entity_pos_t z0, const PathGoal& goal, pass_class_t passClass, WaypointPath& ret) = 0; 97 97 98 98 /** 99 * Compute a tile-based path from the given point to the goal, and return the set of waypoints. 100 * The waypoints correspond to the centers of horizontally/vertically adjacent tiles 101 * along the path. 102 */ 103 virtual void ComputePathCost(entity_pos_t x0, entity_pos_t z0, const PathGoal& goal, pass_class_t passClass, u32& cost) = 0; 104 105 /** 99 106 * Asynchronous version of ComputePath. 100 107 * The result will be sent as CMessagePathResult to 'notify'. 101 108 * Returns a unique non-zero number, which will match the 'ticket' in the result, -
source/simulation2/components/ICmpUnitMotion.cpp
21 21 22 22 #include "simulation2/system/InterfaceScripted.h" 23 23 #include "simulation2/scripting/ScriptComponent.h" 24 25 24 BEGIN_INTERFACE_WRAPPER(UnitMotion) 26 25 DEFINE_INTERFACE_METHOD_4("MoveToPointRange", bool, ICmpUnitMotion, MoveToPointRange, entity_pos_t, entity_pos_t, entity_pos_t, entity_pos_t) 27 26 DEFINE_INTERFACE_METHOD_4("IsInPointRange", bool, ICmpUnitMotion, IsInPointRange, entity_pos_t, entity_pos_t, entity_pos_t, entity_pos_t) … … 29 28 DEFINE_INTERFACE_METHOD_3("MoveToTargetRange", bool, ICmpUnitMotion, MoveToTargetRange, entity_id_t, entity_pos_t, entity_pos_t) 30 29 DEFINE_INTERFACE_METHOD_3("MoveToFormationOffset", void, ICmpUnitMotion, MoveToFormationOffset, entity_id_t, entity_pos_t, entity_pos_t) 31 30 DEFINE_INTERFACE_METHOD_2("FaceTowardsPoint", void, ICmpUnitMotion, FaceTowardsPoint, entity_pos_t, entity_pos_t) 31 DEFINE_INTERFACE_METHOD_2("GetPathCost", u32, ICmpUnitMotion, GetPathCost, entity_pos_t, entity_pos_t) 32 32 DEFINE_INTERFACE_METHOD_0("StopMoving", void, ICmpUnitMotion, StopMoving) 33 33 DEFINE_INTERFACE_METHOD_0("GetCurrentSpeed", fixed, ICmpUnitMotion, GetCurrentSpeed) 34 34 DEFINE_INTERFACE_METHOD_1("SetSpeed", void, ICmpUnitMotion, SetSpeed, fixed) … … 61 61 return m_Script.Call<bool>("IsInTargetRange", target, minRange, maxRange); 62 62 } 63 63 64 virtual u32 GetPathCost(entity_pos_t x, entity_pos_t z) 65 { 66 //Probably not needed for Scripted Movements 67 return -1; 68 } 69 64 70 virtual bool MoveToTargetRange(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange) 65 71 { 66 72 return m_Script.Call<bool>("MoveToTargetRange", target, minRange, maxRange); -
source/simulation2/components/ICmpUnitMotion.h
82 82 virtual void FaceTowardsPoint(entity_pos_t x, entity_pos_t z) = 0; 83 83 84 84 /** 85 * Uses the Long Pathfinder to compute a heuristic cost of the path to the specified point 86 * Can be used to compare acutal travel distance 87 */ 88 virtual u32 GetPathCost(entity_pos_t x, entity_pos_t z) = 0; 89 90 /** 85 91 * Stop moving immediately. 86 92 */ 87 93 virtual void StopMoving() = 0; -
source/simulation2/helpers/LongPathfinder.cpp
782 782 783 783 #undef PASSABLE 784 784 785 void LongPathfinder::ComputeJPSPath(entity_pos_t x0, entity_pos_t z0, const PathGoal& origGoal, pass_class_t passClass, WaypointPath& path )785 void LongPathfinder::ComputeJPSPath(entity_pos_t x0, entity_pos_t z0, const PathGoal& origGoal, pass_class_t passClass, WaypointPath& path, u32* cost) 786 786 { 787 787 PROFILE3("ComputePathJPS"); 788 788 … … 963 963 964 964 // Reconstruct the path (in reverse) 965 965 u16 ip = state.iBest, jp = state.jBest; 966 if (cost) *cost = 0; 966 967 while (ip != i0 || jp != j0) 967 968 { 968 969 PathfindTile& n = state.tiles->get(ip, jp); … … 969 970 entity_pos_t x, z; 970 971 Pathfinding::NavcellCenter(ip, jp, x, z); 971 972 path.m_Waypoints.emplace_back(Waypoint{ x, z }); 973 if (cost) 974 *cost += n.GetCost().ToInt(); 972 975 973 976 // Follow the predecessor link 974 977 ip = n.GetPredI(ip); -
source/simulation2/helpers/LongPathfinder.h
231 231 } 232 232 233 233 /** 234 * Compute a tile-based path from the given point to the goal, and the heuristic cost of following the path. 235 * The waypoints correspond to the centers of horizontally/vertically adjacent tiles 236 * along the path. 237 */ 238 void ComputePathCost(entity_pos_t x0, entity_pos_t z0, const PathGoal& origGoal, 239 pass_class_t passClass, u32& cost) 240 { 241 if (!m_Grid) 242 { 243 LOGERROR("The pathfinder grid hasn't been setup yet, aborting ComputePath"); 244 return; 245 } 246 WaypointPath path; 247 ComputeJPSPath(x0, z0, origGoal, passClass, path, &cost); 248 } 249 250 /** 234 251 * Compute a tile-based path from the given point to the goal, excluding the regions 235 252 * specified in excludedRegions (which are treated as impassable) and return the set of waypoints. 236 253 * The waypoints correspond to the centers of horizontally/vertically adjacent tiles 237 254 * along the path. 238 255 */ 239 void ComputePath(entity_pos_t x0, entity_pos_t z0, const PathGoal& origGoal, 256 void ComputePath(entity_pos_t x0, entity_pos_t z0, const PathGoal& origGoal, 240 257 pass_class_t passClass, std::vector<CircularRegion> excludedRegions, WaypointPath& path); 241 258 242 259 Grid<u16> GetConnectivityGrid(pass_class_t passClass) … … 279 296 * See LongPathfinder.cpp for implementation details 280 297 * TODO: cleanup documentation 281 298 */ 282 void ComputeJPSPath(entity_pos_t x0, entity_pos_t z0, const PathGoal& origGoal, pass_class_t passClass, WaypointPath& path );299 void ComputeJPSPath(entity_pos_t x0, entity_pos_t z0, const PathGoal& origGoal, pass_class_t passClass, WaypointPath& path, u32* cost = NULL); 283 300 void GetDebugDataJPS(u32& steps, double& time, Grid<u8>& grid); 284 301 285 302 // Helper functions for ComputePath