Ticket #3790: remove_planning.patch
File remove_planning.patch, 10.6 KB (added by , 8 years ago) |
---|
-
source/simulation2/components/CCmpUnitMotion.cpp
1 /* Copyright (C) 201 5Wildfire Games.1 /* Copyright (C) 2016 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 109 109 static const CColor OVERLAY_COLOR_LONG_PATH(1, 1, 1, 1); 110 110 static const CColor OVERLAY_COLOR_SHORT_PATH(1, 0, 0, 1); 111 111 112 struct SUnitMotionPlanning113 {114 WaypointPath nextStepShortPath; // if !nextStepClean, store a short path for the next step here115 u32 expectedPathTicket;116 bool nextStepClean; // is there any obstruction between the next two long waypoints?117 118 SUnitMotionPlanning() : expectedPathTicket(0), nextStepClean(true) {}119 };120 121 /**122 * Serialization helper template for SUnitMotionPlanning123 */124 struct SerializeUnitMotionPlanning125 {126 template<typename S>127 void operator()(S& serialize, const char* UNUSED(name), SUnitMotionPlanning& value)128 {129 SerializeVector<SerializeWaypoint>()(serialize, "next step short path", value.nextStepShortPath.m_Waypoints);130 serialize.NumberU32_Unbounded("expected path ticket", value.expectedPathTicket);131 serialize.Bool("next step clean", value.nextStepClean);132 }133 };134 135 112 class CCmpUnitMotion : public ICmpUnitMotion 136 113 { 137 114 public: … … 264 241 265 242 // Motion planning 266 243 u8 m_Tries; // how many tries we've done to get to our current Final Goal. 267 SUnitMotionPlanning m_Planning;268 244 269 245 PathGoal m_FinalGoal; 270 246 … … 336 312 m_ExpectedPathTicket = 0; 337 313 338 314 m_Tries = 0; 339 m_Planning = SUnitMotionPlanning(); 340 315 341 316 m_TargetEntity = INVALID_ENTITY; 342 317 343 318 m_FinalGoal.type = PathGoal::POINT; … … 377 352 SerializeVector<SerializeWaypoint>()(serialize, "long path", m_LongPath.m_Waypoints); 378 353 SerializeVector<SerializeWaypoint>()(serialize, "short path", m_ShortPath.m_Waypoints); 379 354 380 SerializeUnitMotionPlanning()(serialize, "planning", m_Planning);381 382 355 SerializeGoal()(serialize, "goal", m_FinalGoal); 383 356 } 384 357 … … 599 572 CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); 600 573 if (cmpObstruction) 601 574 cmpObstruction->SetMovingFlag(true); 602 575 603 576 m_Moving = true; 604 577 605 578 CMessageMotionChanged msg(true, false); 606 579 GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); 607 580 } … … 634 607 void Move(fixed dt); 635 608 636 609 /** 637 * Analyze our current path, and check if we expect to be obstructed soon638 * If yes, try to anticipate.639 * TODO: remove this and use a more general "pushing" manager.640 */641 void PlanNextStep(const CFixedVector2D& pos, const CFixedVector2D& currentOffset);642 643 /**644 610 * Decide whether to approximate the given range from a square target as a circle, 645 611 * rather than as a square. 646 612 */ … … 697 663 * noTarget is true only when used inside tryGoingStraightToTargetEntity, 698 664 * in which case we do not want the target obstruction otherwise it would always fail 699 665 */ 700 ControlGroupMovementObstructionFilter GetObstructionFilter(bool forceAvoidMovingUnits = false, boolnoTarget = false) const;666 ControlGroupMovementObstructionFilter GetObstructionFilter(bool noTarget = false) const; 701 667 702 668 /** 703 669 * Start moving to the given goal, from our current position 'from'. … … 735 701 736 702 m_Moving = false; 737 703 738 if (ticket == m_Planning.expectedPathTicket)739 {740 // If no path was found, better cancel the planning741 if (path.m_Waypoints.empty())742 m_Planning = SUnitMotionPlanning();743 744 m_Planning.nextStepShortPath = path;745 return;746 }747 748 704 // Ignore obsolete path requests 749 705 if (ticket != m_ExpectedPathTicket) 750 706 return; … … 785 741 786 742 if (cmpObstruction) 787 743 cmpObstruction->SetMovingFlag(true); 788 744 789 745 m_Moving = true; 790 746 } 791 747 else if (m_PathState == PATHSTATE_WAITING_REQUESTING_SHORT || m_PathState == PATHSTATE_FOLLOWING_REQUESTING_SHORT) … … 808 764 GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); 809 765 return; 810 766 } 811 767 812 768 CMessageMotionChanged msg(false, false); 813 769 GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); 814 770 … … 815 771 CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle()); 816 772 if (!cmpPosition || !cmpPosition->IsInWorld()) 817 773 return; 818 774 819 775 CFixedVector2D pos = cmpPosition->GetPosition2D(); 820 776 821 777 if (ShouldConsiderOurselvesAtDestination(pos)) … … 829 785 830 786 // else we could, so reset our number of tries. 831 787 m_Tries = 0; 832 788 833 789 // Now we've got a short path that we can follow 834 790 if (!HasValidPath()) 835 791 StartSucceeded(); … … 842 798 m_Moving = true; 843 799 } 844 800 else 845 {846 801 LOGWARNING("unexpected PathResult (%u %d %d)", GetEntityId(), m_State, m_PathState); 847 }848 802 } 849 803 850 804 void CCmpUnitMotion::Move(fixed dt) … … 926 880 927 881 fixed timeLeft = dt; 928 882 fixed zero = fixed::Zero(); 929 883 930 884 while (timeLeft > zero) 931 885 { 932 886 // If we ran out of path, we have to stop … … 976 930 target = pos + offset; 977 931 978 932 if (cmpPathfinder->CheckMovement(GetObstructionFilter(), pos.X, pos.Y, target.X, target.Y, m_Clearance, m_PassClass)) 979 {980 PlanNextStep(pos, offset);981 933 pos = target; 982 break;983 }984 934 else 985 { 986 // Error - path was obstructed 987 wasObstructed = true; 988 break; 989 } 935 wasObstructed = true; // Error - path was obstructed 936 937 break; 990 938 } 991 939 } 992 940 … … 994 942 if (pos != initialPos) 995 943 { 996 944 CFixedVector2D offset = pos - initialPos; 997 945 998 946 // Face towards the target 999 947 entity_angle_t angle = atan2_approx(offset.X, offset.Y); 1000 948 cmpPosition->MoveAndTurnTo(pos.X,pos.Y, angle); … … 1002 950 // Calculate the mean speed over this past turn. 1003 951 m_CurSpeed = cmpPosition->GetDistanceTravelled() / dt; 1004 952 } 1005 953 1006 954 if (wasObstructed) 1007 955 { 1008 956 // Oops, we hit something (very likely another unit). 1009 957 // This is when we might easily get stuck wrongly. 1010 958 1011 959 // check if we've arrived. 1012 960 if (ShouldConsiderOurselvesAtDestination(pos)) 1013 961 return; 1014 962 1015 963 // If we still have long waypoints, try and compute a short path 1016 964 // This will get us around units, amongst others. 1017 965 // However in some cases a long waypoint will be in located in the obstruction of … … 1032 980 square.z = m_LongPath.m_Waypoints.back().z; 1033 981 std::vector<entity_id_t> unitOnGoal; 1034 982 // don't ignore moving units as those might be units like us, ie not really moving. 1035 cmpObstructionManager->GetUnitsOnObstruction(square, unitOnGoal, GetObstructionFilter( false, false), true);983 cmpObstructionManager->GetUnitsOnObstruction(square, unitOnGoal, GetObstructionFilter(), true); 1036 984 if (!unitOnGoal.empty()) 1037 985 m_LongPath.m_Waypoints.pop_back(); 1038 986 } … … 1119 1067 } 1120 1068 } 1121 1069 1122 void CCmpUnitMotion::PlanNextStep(const CFixedVector2D& pos, const CFixedVector2D& currentOffset)1123 {1124 if (m_LongPath.m_Waypoints.empty())1125 return;1126 1127 CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity());1128 CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());1129 if (!cmpPathfinder || !cmpObstructionManager)1130 return;1131 1132 m_Planning = SUnitMotionPlanning();1133 1134 // see 2 turns in advance, otherwise this would start to lag in MP1135 CFixedVector2D futurePos = pos + currentOffset*2;1136 1137 // Don't actually use CheckMovement since we want to check against units only, we assume the rest is taken care of.1138 if (!cmpObstructionManager->TestLine(GetObstructionFilter(true, false), pos.X, pos.Y, futurePos.X, futurePos.Y, m_Clearance, true))1139 return;1140 1141 // we will run into a static unit obstruction. Try to shortpath around it.1142 PathGoal goal;1143 if (m_LongPath.m_Waypoints.size() > 1 || m_FinalGoal.DistanceToPoint(pos) > LONG_PATH_MIN_DIST)1144 goal = { PathGoal::POINT, m_LongPath.m_Waypoints.back().x, m_LongPath.m_Waypoints.back().z };1145 else1146 {1147 UpdateFinalGoal();1148 goal = m_FinalGoal;1149 m_LongPath.m_Waypoints.clear();1150 CFixedVector2D target = goal.NearestPointOnGoal(pos);1151 m_LongPath.m_Waypoints.emplace_back(Waypoint{ target.X, target.Y });1152 }1153 RequestShortPath(pos, goal, false);1154 m_PathState = PATHSTATE_FOLLOWING_REQUESTING_SHORT;1155 }1156 1157 1070 bool CCmpUnitMotion::ComputeTargetPosition(CFixedVector2D& out) 1158 1071 { 1159 1072 if (m_TargetEntity == INVALID_ENTITY) … … 1230 1143 CFixedVector2D goalPos = goal.NearestPointOnGoal(from); 1231 1144 1232 1145 // Check if there's any collisions on that route 1233 if (!cmpPathfinder->CheckMovement(GetObstructionFilter( false,true), from.X, from.Y, goalPos.X, goalPos.Y, m_Clearance, m_PassClass))1146 if (!cmpPathfinder->CheckMovement(GetObstructionFilter(true), from.X, from.Y, goalPos.X, goalPos.Y, m_Clearance, m_PassClass)) 1234 1147 return false; 1235 1148 1236 1149 // That route is okay, so update our path … … 1309 1222 { 1310 1223 if (m_TargetEntity != INVALID_ENTITY || m_FinalGoal.DistanceToPoint(from) > SHORT_PATH_GOAL_RADIUS) 1311 1224 return false; 1312 1225 1313 1226 StopMoving(); 1314 1227 MoveSucceeded(); 1315 1228 1316 1229 if (m_FacePointAfterMove) 1317 1230 FaceTowardsPointFromPos(from, m_FinalGoal.x, m_FinalGoal.z); 1318 1231 return true; … … 1365 1278 } 1366 1279 } 1367 1280 1368 ControlGroupMovementObstructionFilter CCmpUnitMotion::GetObstructionFilter(bool forceAvoidMovingUnits, boolnoTarget) const1281 ControlGroupMovementObstructionFilter CCmpUnitMotion::GetObstructionFilter(bool noTarget) const 1369 1282 { 1370 1283 entity_id_t group = noTarget ? m_TargetEntity : GetGroup(); 1371 return ControlGroupMovementObstructionFilter( forceAvoidMovingUnits ||ShouldAvoidMovingUnits(), group);1284 return ControlGroupMovementObstructionFilter(ShouldAvoidMovingUnits(), group); 1372 1285 } 1373 1286 1374 1287 … … 1377 1290 { 1378 1291 // reset our state for sanity. 1379 1292 m_ExpectedPathTicket = 0; 1380 1293 1381 1294 CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); 1382 1295 if (cmpObstruction) 1383 1296 cmpObstruction->SetMovingFlag(false); 1384 1297 1385 1298 m_Moving = false; 1386 1299 1387 1300 m_PathState = PATHSTATE_NONE; … … 1470 1383 searchRange = std::min(goal.hw, SHORT_PATH_MIN_SEARCH_RANGE * 2); 1471 1384 if (searchRange > SHORT_PATH_MAX_SEARCH_RANGE) 1472 1385 searchRange = SHORT_PATH_MAX_SEARCH_RANGE; 1473 1386 1474 1387 m_ExpectedPathTicket = cmpPathfinder->ComputeShortPathAsync(from.X, from.Y, m_Clearance, searchRange, goal, m_PassClass, avoidMovingUnits, GetGroup(), GetEntityId()); 1475 1388 } 1476 1389 … … 1559 1472 CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity()); 1560 1473 ICmpObstructionManager::ObstructionSquare obstruction; 1561 1474 //TODO if (cmpObstructionManager) 1562 // hasObstruction = cmpObstructionManager->FindMostImportantObstruction(GetObstructionFilter( true), x, z, m_Radius, obstruction);1475 // hasObstruction = cmpObstructionManager->FindMostImportantObstruction(GetObstructionFilter(), x, z, m_Radius, obstruction); 1563 1476 1564 1477 if (minRange.IsZero() && maxRange.IsZero() && hasObstruction) 1565 1478 {