| 596 | } |
| 597 | |
| 598 | std::list<Vec3<int>> Battle::findShortestPathUsingLB(Vec3<int> origin, Vec3<int> destination, |
| 599 | const BattleUnitTileHelper &canEnterTile, |
| 600 | bool approachOnly, bool ignoreStaticUnits, |
| 601 | bool ignoreMovingUnits, bool ignoreAllUnits, |
| 602 | float *cost, float maxCost) |
| 603 | { |
| 604 | // How much attempts are given to the pathfinding until giving up and concluding that |
| 605 | // there is no simple path between orig and dest. This is a multiplier for "distance", which is |
| 606 | // a minimum number of iterations required to pathfind between two locations |
| 607 | static const int PATH_ITERATION_LIMIT_MULTIPLIER = 2; |
| 608 | |
| 609 | // Same as PATH_ITERATION_LIMIT_MULTIPLIER but for when navigating to next los block |
| 610 | static const int GRAPH_ITERATION_LIMIT_MULTIPLIER = 2; |
| 611 | |
| 612 | // Extra iterations allowed when pathing to a los block, because if we need |
| 613 | // to find a door we can have a hard time doing so |
| 614 | static const int GRAPH_ITERATION_LIMIT_EXTRA = 50; |
| 615 | |
| 616 | int distance = canEnterTile.getDistance(origin, destination) / 4.0f; |
| 617 | std::list<Vec3<int>> result; |
| 618 | |
| 619 | // Pathfind on graphs of los blocks |
| 620 | int startLB = getLosBlockID(origin.x, origin.y, origin.z); |
| 621 | int destLB = getLosBlockID(destination.x, destination.y, destination.z); |
| 622 | auto pathLB = findLosBlockPath(startLB, destLB, canEnterTile.getType()); |
| 623 | |
| 624 | // If pathfinding on graphs failed - return short part of the path towards target |
| 625 | if ((*pathLB.rbegin()) != destLB) |
| 626 | { |
| 627 | if (!result.empty()) |
| 628 | { |
| 629 | return result; |
| 630 | } |
| 631 | else |
| 632 | { |
| 633 | return map->findShortestPath( |
| 634 | origin, destination, distance * PATH_ITERATION_LIMIT_MULTIPLIER, canEnterTile, |
| 635 | approachOnly, ignoreStaticUnits, ignoreMovingUnits, ignoreAllUnits, cost, maxCost); |
| 636 | } |
| 637 | } |
| 638 | |
| 639 | // Step 01: Pathfind using path among blocks |
| 640 | |
| 641 | result.clear(); |
| 642 | result.push_back(origin); |
| 643 | if (cost) |
| 644 | { |
| 645 | *cost = 0.0f; |
| 646 | } |
| 647 | float curMaxCost = maxCost; |
| 648 | while (!pathLB.empty()) |
| 649 | { |
| 650 | auto curOrigin = *result.rbegin(); |
| 651 | float curCost = 0.0f; |
| 652 | auto lbID = pathLB.front(); |
| 653 | pathLB.pop_front(); |
| 654 | auto &lb = *losBlocks[lbID]; |
| 655 | auto distToNext = canEnterTile.getDistance(curOrigin, (lb.start + lb.end) / 2) / 4.0f; |
nothing calls this directly
no test coverage detected