Ticket #3410: revert_16998.patch
File revert_16998.patch, 13.3 KB (added by , 9 years ago) |
---|
-
source/simulation2/MessageTypes.h
538 538 } 539 539 }; 540 540 541 /**542 * Sent when the pathfinder's passability map is modified on update543 */544 class CMessagePassabilityMapChanged : public CMessage545 {546 public:547 DEFAULT_MESSAGE_IMPL(PassabilityMapChanged)548 549 CMessagePassabilityMapChanged()550 {551 }552 };553 554 541 #endif // INCLUDED_MESSAGETYPES -
source/simulation2/TypeList.h
57 57 MESSAGE(TemplateModification) 58 58 MESSAGE(VisionRangeChanged) 59 59 MESSAGE(MinimapPing) 60 MESSAGE(PassabilityMapChanged)61 60 62 61 // TemplateManager must come before all other (non-test) components, 63 62 // so that it is the first to be (de)serialized -
source/simulation2/components/CCmpUnitMotion.cpp
135 135 componentManager.SubscribeToMessageType(MT_PathResult); 136 136 componentManager.SubscribeToMessageType(MT_ValueModification); 137 137 componentManager.SubscribeToMessageType(MT_Deserialized); 138 componentManager.SubscribeToMessageType(MT_PassabilityMapChanged);139 138 } 140 139 141 140 DEFAULT_COMPONENT_ALLOCATOR(UnitMotion) … … 255 254 WaypointPath m_LongPath; 256 255 WaypointPath m_ShortPath; 257 256 258 // When the passability map has changed, we cannot fully trust the path computed by the259 // pathfinder before that change.260 bool m_PassabilityMapChangedRecently;261 262 257 // Motion planning 263 258 SUnitMotionPlanning m_Planning; 264 259 … … 331 326 332 327 m_ExpectedPathTicket = 0; 333 328 334 m_PassabilityMapChangedRecently = false;335 336 329 m_TargetEntity = INVALID_ENTITY; 337 330 338 331 m_FinalGoal.type = PathGoal::POINT; … … 369 362 370 363 SerializeVector<SerializeWaypoint>()(serialize, "long path", m_LongPath.m_Waypoints); 371 364 SerializeVector<SerializeWaypoint>()(serialize, "short path", m_ShortPath.m_Waypoints); 372 serialize.Bool("passability map changed recently", m_PassabilityMapChangedRecently);373 365 374 366 SerializeUnitMotionPlanning()(serialize, "planning", m_Planning); 375 367 … … 453 445 m_RunSpeed = newRunSpeed; 454 446 break; 455 447 } 456 case MT_PassabilityMapChanged:457 m_PassabilityMapChangedRecently = true;458 break;459 448 } 460 449 } 461 450 … … 668 657 /** 669 658 * Returns an appropriate obstruction filter for use with path requests. 670 659 */ 671 ControlGroupMovementObstructionFilter GetObstructionFilter(bool avoidPathfindingShapes) const;660 ControlGroupMovementObstructionFilter GetObstructionFilter(bool forceAvoidMovingUnits = false) const; 672 661 673 662 /** 674 * Checks our movement towards the next path waypoint.675 * Pathfinding-blocking shapes are assumed to be taken into account during the path computation676 * and this will only be used to avoid moving units.677 */678 bool CheckMovement(entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1) const;679 680 /**681 663 * Start moving to the given goal, from our current position 'from'. 682 664 * Might go in a straight line immediately, or might start an asynchronous 683 665 * path request. … … 735 717 736 718 if (m_PathState == PATHSTATE_WAITING_REQUESTING_LONG || m_PathState == PATHSTATE_FOLLOWING_REQUESTING_LONG) 737 719 { 738 m_PassabilityMapChangedRecently = false;739 740 720 m_LongPath = path; 741 721 742 722 // If we are following a path, leave the old m_ShortPath so we can carry on following it … … 852 832 // Maybe we should split the updates into multiple phases to minimise 853 833 // that problem. 854 834 835 CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity()); 836 if (!cmpPathfinder) 837 return; 838 855 839 CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle()); 856 840 if (!cmpPosition || !cmpPosition->IsInWorld()) 857 841 return; … … 911 895 fixed offsetLength = offset.Length(); 912 896 if (offsetLength <= maxdist) 913 897 { 914 if ( CheckMovement(pos.X, pos.Y, target.X, target.Y))898 if (cmpPathfinder->CheckMovement(GetObstructionFilter(), pos.X, pos.Y, target.X, target.Y, m_Clearance, m_PassClass)) 915 899 { 916 900 pos = target; 917 901 … … 941 925 offset.Normalize(maxdist); 942 926 target = pos + offset; 943 927 944 if ( CheckMovement(pos.X, pos.Y, target.X, target.Y))928 if (cmpPathfinder->CheckMovement(GetObstructionFilter(), pos.X, pos.Y, target.X, target.Y, m_Clearance, m_PassClass)) 945 929 { 946 930 pos = target; 947 931 break; … … 970 954 971 955 if (wasObstructed) 972 956 { 973 // Oops, we hit something (very likely another unit , or a new obstruction).957 // Oops, we hit something (very likely another unit). 974 958 // Stop, and recompute the whole path. 975 959 // TODO: if the target has UnitMotion and is higher priority, 976 960 // we should wait a little bit. 977 961 978 962 // Recompute our path 979 // If we are following a long path and it is still valid980 if (!m_LongPath.m_Waypoints.empty() && !m_PassabilityMapChangedRecently)963 // If we are following a long path 964 if (!m_LongPath.m_Waypoints.empty()) 981 965 { 982 966 PathGoal goal = { PathGoal::POINT, m_LongPath.m_Waypoints.back().x, m_LongPath.m_Waypoints.back().z }; 983 967 RequestShortPath(pos, goal, true); … … 1050 1034 if (m_LongPath.m_Waypoints.empty()) 1051 1035 return; 1052 1036 1037 CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity()); 1053 1038 1054 1039 const Waypoint& nextPoint = m_LongPath.m_Waypoints.back(); 1055 1040 1056 1041 // The next step was obstructed the last time we checked; also check that 1057 1042 // the step is still obstructed (maybe the units in our way moved in the meantime) 1058 if (!m_Planning.nextStepClean && CheckMovement(pos.X, pos.Y, nextPoint.x, nextPoint.z)) 1043 if (!m_Planning.nextStepClean && 1044 !cmpPathfinder->CheckMovement(GetObstructionFilter(), pos.X, pos.Y, nextPoint.x, nextPoint.z, m_Clearance, m_PassClass)) 1059 1045 { 1060 1046 // If the short path computation is over, use it, else just forget about it 1061 1047 if (!m_Planning.nextStepShortPath.m_Waypoints.empty()) … … 1071 1057 return; 1072 1058 1073 1059 const Waypoint& followingPoint = m_LongPath.m_Waypoints.rbegin()[1]; // penultimate element 1074 m_Planning.nextStepClean = CheckMovement(nextPoint.x, nextPoint.z, followingPoint.x, followingPoint.z); 1060 m_Planning.nextStepClean = cmpPathfinder->CheckMovement( 1061 GetObstructionFilter(), nextPoint.x, nextPoint.z, followingPoint.x, followingPoint.z, m_Clearance, m_PassClass); 1075 1062 if (!m_Planning.nextStepClean) 1076 1063 { 1077 CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity());1078 if (!cmpPathfinder)1079 return;1080 1081 1064 PathGoal goal = { PathGoal::POINT, followingPoint.x, followingPoint.z }; 1082 1065 m_Planning.expectedPathTicket = cmpPathfinder->ComputeShortPathAsync( 1083 1066 nextPoint.x, nextPoint.z, m_Clearance, SHORT_PATH_SEARCH_RANGE, goal, m_PassClass, false, m_TargetEntity, GetEntityId()); … … 1124 1107 return false; 1125 1108 1126 1109 // Check if there's any collisions on that route 1127 if (!cmpPathfinder->CheckMovement(GetObstructionFilter( true), from.X, from.Y, goalPos.X, goalPos.Y, m_Clearance, m_PassClass))1110 if (!cmpPathfinder->CheckMovement(GetObstructionFilter(), from.X, from.Y, goalPos.X, goalPos.Y, m_Clearance, m_PassClass)) 1128 1111 return false; 1129 1112 1130 1113 // That route is okay, so update our path … … 1160 1143 CFixedVector2D goalPos = goal.NearestPointOnGoal(from); 1161 1144 1162 1145 // Check if there's any collisions on that route 1163 if (!cmpPathfinder->CheckMovement(GetObstructionFilter( true), from.X, from.Y, goalPos.X, goalPos.Y, m_Clearance, m_PassClass))1146 if (!cmpPathfinder->CheckMovement(GetObstructionFilter(), from.X, from.Y, goalPos.X, goalPos.Y, m_Clearance, m_PassClass)) 1164 1147 return false; 1165 1148 1166 1149 // That route is okay, so update our path … … 1268 1251 } 1269 1252 } 1270 1253 1271 ControlGroupMovementObstructionFilter CCmpUnitMotion::GetObstructionFilter(bool avoidPathfindingShapes) const1254 ControlGroupMovementObstructionFilter CCmpUnitMotion::GetObstructionFilter(bool forceAvoidMovingUnits) const 1272 1255 { 1273 1256 entity_id_t group; 1274 1257 if (IsFormationMember()) … … 1276 1259 else 1277 1260 group = GetEntityId(); 1278 1261 1279 return ControlGroupMovementObstructionFilter( avoidPathfindingShapes,ShouldAvoidMovingUnits(), group);1262 return ControlGroupMovementObstructionFilter(forceAvoidMovingUnits || ShouldAvoidMovingUnits(), group); 1280 1263 } 1281 1264 1282 bool CCmpUnitMotion::CheckMovement(entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1) const1283 {1284 // If the passability map has changed, we have to check everything in our way until we compute a new path.1285 if (m_PassabilityMapChangedRecently)1286 {1287 CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity());1288 return cmpPathfinder && cmpPathfinder->CheckMovement(GetObstructionFilter(true), x0, z0, x1, z1, m_Clearance, m_PassClass);1289 }1290 1265 1291 // If an obstruction blocks tile-based pathfinding, it will be handled during the path computation1292 // and doesn't need to be matched by this filter for the movement.1293 ControlGroupMovementObstructionFilter filter = GetObstructionFilter(false);1294 1266 1295 CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());1296 return cmpObstructionManager && !cmpObstructionManager->TestLine(filter, x0, z0, x1, z1, m_Clearance);1297 }1298 1299 1300 1267 void CCmpUnitMotion::BeginPathing(const CFixedVector2D& from, const PathGoal& goal) 1301 1268 { 1302 1269 // Cancel any pending path requests … … 1310 1277 if (cmpObstruction) 1311 1278 cmpObstruction->SetMovingFlag(true); 1312 1279 1313 // We are going to recompute our path, so we will use the most recent passability grid1314 m_PassabilityMapChangedRecently = false;1315 1316 1280 #if DISABLE_PATHFINDER 1317 1281 { 1318 1282 CmpPtr<ICmpPathfinder> cmpPathfinder (GetSimContext(), SYSTEM_ENTITY); -
source/simulation2/components/ICmpObstructionManager.h
323 323 */ 324 324 class ControlGroupMovementObstructionFilter : public IObstructionTestFilter 325 325 { 326 bool m_AvoidPathfindingShapes;327 326 bool m_AvoidMoving; 328 327 entity_id_t m_Group; 329 328 330 329 public: 331 ControlGroupMovementObstructionFilter(bool avoid PathfindingShapes, bool avoidMoving, entity_id_t group) :332 m_Avoid PathfindingShapes(avoidPathfindingShapes), m_AvoidMoving(avoidMoving), m_Group(group)330 ControlGroupMovementObstructionFilter(bool avoidMoving, entity_id_t group) : 331 m_AvoidMoving(avoidMoving), m_Group(group) 333 332 {} 334 333 335 334 virtual bool TestShape(tag_t UNUSED(tag), flags_t flags, entity_id_t group, entity_id_t group2) const … … 337 336 if (group == m_Group || (group2 != INVALID_ENTITY && group2 == m_Group)) 338 337 return false; 339 338 340 if ((flags & ICmpObstructionManager::FLAG_BLOCK_PATHFINDING) && !m_AvoidPathfindingShapes)341 return false;342 343 339 if (!(flags & ICmpObstructionManager::FLAG_BLOCK_MOVEMENT)) 344 340 return false; 345 341 -
source/simulation2/components/CCmpPathfinder.cpp
522 522 } 523 523 else 524 524 m_LongPathfinder.Update(m_Grid, m_ObstructionsDirty.dirtinessGrid); 525 526 // Notify the units that their current paths can be invalid now.527 // The passability map will be globally dirty after init, or rejoining, loading a saved game, etc.528 // In those situations the paths can't be invalid.529 if (!m_ObstructionsDirty.globallyDirty)530 {531 CMessagePassabilityMapChanged msg;532 GetSimContext().GetComponentManager().BroadcastMessage(msg);533 525 } 534 }535 526 536 527 void CCmpPathfinder::MinimalTerrainUpdate() 537 528 { … … 727 718 { 728 719 const AsyncShortPathRequest& req = shortRequests[i]; 729 720 WaypointPath path; 730 ControlGroupMovementObstructionFilter filter( true,req.avoidMovingUnits, req.group);721 ControlGroupMovementObstructionFilter filter(req.avoidMovingUnits, req.group); 731 722 ComputeShortPath(filter, req.x0, req.z0, req.clearance, req.range, req.goal, req.passClass, path); 732 723 CMessagePathResult msg(req.ticket, path); 733 724 GetSimContext().GetComponentManager().PostMessage(req.notify, msg); -
source/simulation2/scripting/MessageTypeConversions.cpp
1 /* Copyright (C) 201 5Wildfire Games.1 /* Copyright (C) 2014 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 … … 470 470 return new CMessageMinimapPing(); 471 471 } 472 472 473 ////////////////////////////////474 475 JS::Value CMessagePassabilityMapChanged::ToJSVal(ScriptInterface& scriptInterface) const476 {477 TOJSVAL_SETUP();478 return JS::ObjectValue(*obj);479 }480 481 CMessage* CMessagePassabilityMapChanged::FromJSVal(ScriptInterface& UNUSED(scriptInterface), JS::HandleValue UNUSED(val))482 {483 return new CMessagePassabilityMapChanged();484 }485 486 473 //////////////////////////////////////////////////////////////// 487 474 488 475 CMessage* CMessageFromJSVal(int mtid, ScriptInterface& scriptingInterface, JS::HandleValue val)