Ticket #4327: pathfinderFix.patch
File pathfinderFix.patch, 8.5 KB (added by , 7 years ago) |
---|
-
source/simulation2/components/CCmpPathfinder_Vertex.cpp
diff --git a/source/simulation2/components/CCmpPathfinder_Vertex.cpp b/source/simulation2/components/CCmpPathfinder_Vertex.cpp index ab180b3..6e52e27 100644
a b void CCmpPathfinder::ComputeShortPath(const IObstructionTestFilter& filter, 592 592 entity_pos_t pathfindClearance = clearance; 593 593 594 594 // Convert each obstruction square into collision edges and search graph vertexes 595 // We also expand our range if vertices fall outside of it, so that all required terrain edges are added. 595 596 for (size_t i = 0; i < squares.size(); ++i) 596 597 { 597 598 CFixedVector2D center(squares[i].x, squares[i].z); -
source/simulation2/components/CCmpUnitMotion.cpp
diff --git a/source/simulation2/components/CCmpUnitMotion.cpp b/source/simulation2/components/CCmpUnitMotion.cpp index 04a7a00..e526221 100644
a b public: 217 217 */ 218 218 PATHSTATE_FOLLOWING_REQUESTING_SHORT, 219 219 220 /* 221 * We ran out of waypoints and were not really close to our final destination 222 * There is a possibility the short-range pathfinder will find a better path 223 * since the long-range rasterization is less permissive 224 * So we'll request one final short path. If it fails, we fail. 225 */ 226 PATHSTATE_ARRIVED_TRYING_SHORT, 227 220 228 PATHSTATE_MAX 221 229 }; 222 230 u8 m_PathState; … … private: 639 647 void UpdateFinalGoal(); 640 648 641 649 /** 642 * Returns whether we are close enough to the target to assume it's a good enough 643 * position to stop. 650 * Returns if we are close enough to safely assume we've arrived. 651 */ 652 bool IsAtDestination(const CFixedVector2D& from); 653 654 /** 655 * If we are close enough to stop, succeed the move. 644 656 */ 645 657 bool ShouldConsiderOurselvesAtDestination(const CFixedVector2D& from); 646 658 … … void CCmpUnitMotion::PathResult(u32 ticket, const WaypointPath& path) 741 753 742 754 m_Moving = true; 743 755 } 744 else if (m_PathState == PATHSTATE_WAITING_REQUESTING_SHORT || m_PathState == PATHSTATE_FOLLOWING_REQUESTING_SHORT) 756 else if (m_PathState == PATHSTATE_WAITING_REQUESTING_SHORT || m_PathState == PATHSTATE_FOLLOWING_REQUESTING_SHORT 757 || m_PathState == PATHSTATE_ARRIVED_TRYING_SHORT) 745 758 { 746 759 m_ShortPath = path; 747 748 760 // If there's no waypoints then we couldn't get near the target 749 761 if (m_ShortPath.m_Waypoints.empty()) 750 762 { 763 CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle()); 764 765 if (!cmpPosition || !cmpPosition->IsInWorld()) 766 return; 767 768 CFixedVector2D pos = cmpPosition->GetPosition2D(); 769 770 // we failed to improve on our path 771 if (m_PathState == PATHSTATE_ARRIVED_TRYING_SHORT) 772 { 773 StopMoving(); 774 m_State = STATE_IDLE; 775 // two options: if we were just moving there, succeed: we got as close as we could. 776 // if we were targeting an entity, only succeed if we're in range 777 if (!m_TargetEntity || IsInTargetRange(m_TargetEntity, m_TargetMinRange, m_TargetMaxRange)) 778 { 779 MoveSucceeded(); 780 781 if (m_FacePointAfterMove) 782 FaceTowardsPointFromPos(pos, m_FinalGoal.x, m_FinalGoal.z); 783 return; 784 } 785 // we actually failed. 786 MoveFailed(); 787 return; 788 } 789 751 790 // If we're globally following a long path, try to remove the next waypoint, it might be obstructed 752 791 // If not, and we are not in a formation, retry 753 792 // unless we are close to our target and we don't have a target entity. … … void CCmpUnitMotion::PathResult(u32 ticket, const WaypointPath& path) 765 804 CMessageMotionChanged msg(false, false); 766 805 GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); 767 806 768 CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());769 if (!cmpPosition || !cmpPosition->IsInWorld())770 return;771 772 CFixedVector2D pos = cmpPosition->GetPosition2D();773 774 807 if (ShouldConsiderOurselvesAtDestination(pos)) 775 808 return; 776 809 … … void CCmpUnitMotion::Move(fixed dt) 1011 1044 1012 1045 if (m_PathState == PATHSTATE_FOLLOWING) 1013 1046 { 1014 // If we're not currently computing any new paths:1015 if (m_LongPath.m_Waypoints.empty() && m_ShortPath.m_Waypoints.empty())1016 {1017 if (IsFormationMember())1018 {1019 // We've reached our assigned position. If the controller1020 // is idle, send a notification in case it should disband,1021 // otherwise continue following the formation next turn.1022 CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), m_TargetEntity);1023 if (cmpUnitMotion && !cmpUnitMotion->IsMoving())1024 {1025 CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle());1026 if (cmpObstruction)1027 cmpObstruction->SetMovingFlag(false);1028 1029 m_Moving = false;1030 CMessageMotionChanged msg(false, false);1031 GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg);1032 }1033 }1034 else1035 {1036 // check if target was reached in case of a moving target1037 CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), m_TargetEntity);1038 if (cmpUnitMotion && cmpUnitMotion->IsMoving() &&1039 MoveToTargetRange(m_TargetEntity, m_TargetMinRange, m_TargetMaxRange))1040 return;1041 1042 // Not in formation, so just finish moving1043 StopMoving();1044 m_State = STATE_IDLE;1045 MoveSucceeded();1046 1047 if (m_FacePointAfterMove)1048 FaceTowardsPointFromPos(pos, m_FinalGoal.x, m_FinalGoal.z);1049 // TODO: if the goal was a square building, we ought to point towards the1050 // nearest point on the square, not towards its center1051 }1052 }1053 1054 1047 // If we have a target entity, and we're not miles away from the end of 1055 1048 // our current path, and the target moved enough, then recompute our 1056 1049 // whole path 1050 bool followingTarget = false; 1057 1051 if (IsFormationMember()) 1058 CheckTargetMovement(pos, CHECK_TARGET_MOVEMENT_MIN_DELTA_FORMATION);1052 followingTarget = CheckTargetMovement(pos, CHECK_TARGET_MOVEMENT_MIN_DELTA_FORMATION); 1059 1053 else 1060 CheckTargetMovement(pos, CHECK_TARGET_MOVEMENT_MIN_DELTA); 1054 followingTarget = CheckTargetMovement(pos, CHECK_TARGET_MOVEMENT_MIN_DELTA); 1055 1056 if (followingTarget) 1057 return; 1058 1059 // If we are still going to compute a path, return. 1060 if (!m_LongPath.m_Waypoints.empty() || !m_ShortPath.m_Waypoints.empty()) 1061 return; 1062 1063 // if we dont believe we're actually arrived, presumably the long-range pathfinder's path was a little bad 1064 // probably because it over-rasterized. Retry a new long path, which will pop us in recovery mode if necessary. 1065 if (!ShouldConsiderOurselvesAtDestination(pos)) 1066 { 1067 m_PathState = PATHSTATE_ARRIVED_TRYING_SHORT; 1068 RequestShortPath(pos, m_FinalGoal, true); 1069 return; 1070 } 1061 1071 } 1062 1072 } 1063 1073 } … … void CCmpUnitMotion::UpdateFinalGoal() 1213 1223 m_FinalGoal.z = targetPos.Y; 1214 1224 } 1215 1225 1226 bool CCmpUnitMotion::IsAtDestination(const CFixedVector2D& from) 1227 { 1228 return ((m_TargetEntity != INVALID_ENTITY && IsInTargetRange(m_TargetEntity, m_TargetMinRange, m_TargetMaxRange)) 1229 || m_FinalGoal.DistanceToPoint(from) <= SHORT_PATH_GOAL_RADIUS); 1230 } 1231 1216 1232 bool CCmpUnitMotion::ShouldConsiderOurselvesAtDestination(const CFixedVector2D& from) 1217 1233 { 1218 if ( m_TargetEntity != INVALID_ENTITY || m_FinalGoal.DistanceToPoint(from) > SHORT_PATH_GOAL_RADIUS)1234 if (!IsAtDestination(from)) 1219 1235 return false; 1220 1236 1221 StopMoving(); 1222 MoveSucceeded(); 1237 if (IsFormationMember()) 1238 { 1239 // We've reached our assigned position. If the controller 1240 // is idle, send a notification in case it should disband, 1241 // otherwise continue following the formation next turn. 1242 CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), m_TargetEntity); 1243 if (cmpUnitMotion && !cmpUnitMotion->IsMoving()) 1244 { 1245 CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); 1246 if (cmpObstruction) 1247 cmpObstruction->SetMovingFlag(false); 1248 1249 m_Moving = false; 1250 CMessageMotionChanged msg(false, false); 1251 GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); 1252 } 1253 } 1254 else 1255 { 1256 // check if target was reached in case of a moving target 1257 CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), m_TargetEntity); 1258 if (cmpUnitMotion && cmpUnitMotion->IsMoving() && 1259 MoveToTargetRange(m_TargetEntity, m_TargetMinRange, m_TargetMaxRange)) 1260 return true; 1223 1261 1224 if (m_FacePointAfterMove) 1225 FaceTowardsPointFromPos(from, m_FinalGoal.x, m_FinalGoal.z); 1262 // Not in formation, so just finish moving 1263 StopMoving(); 1264 m_State = STATE_IDLE; 1265 MoveSucceeded(); 1266 1267 if (m_FacePointAfterMove) 1268 FaceTowardsPointFromPos(from, m_FinalGoal.x, m_FinalGoal.z); 1269 // TODO: if the goal was a square building, we ought to point towards the 1270 // nearest point on the square, not towards its center 1271 } 1226 1272 return true; 1227 1273 } 1228 1274