739 | | |
740 | | // If there's no waypoints then we couldn't get near the target |
741 | | if (m_ShortPath.m_Waypoints.empty()) |
742 | | { |
743 | | // If we're globally following a long path, try to remove the next waypoint, it might be obstructed |
744 | | if (m_LongPath.m_Waypoints.size() > 1) |
745 | | m_LongPath.m_Waypoints.pop_back(); |
746 | | else if (!IsFormationMember()) |
747 | | { |
748 | | StartFailed(); |
749 | | return; |
750 | | } |
751 | | else |
752 | | { |
753 | | m_Moving = false; |
754 | | CMessageMotionChanged msg(true, true); |
755 | | GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); |
756 | | } |
757 | | } |
758 | | |
| 739 | |
767 | | m_PathState = PATHSTATE_FOLLOWING; |
| 749 | |
| 750 | if (!m_ShortPath.m_Waypoints.empty()) |
| 751 | { |
| 752 | m_PathState = PATHSTATE_FOLLOWING; |
| 753 | StartSucceeded(); |
| 754 | } |
| 755 | else |
| 756 | { |
| 757 | CMessageMotionChanged msg(false, true); |
| 758 | GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); |
| 759 | m_ExpectedPathTicket = 0; |
| 760 | m_ShortPath.m_Waypoints.clear(); |
| 761 | |
| 762 | CmpPtr<ICmpObstruction> cmpObstruction(GetEntityHandle()); |
| 763 | if (cmpObstruction) |
| 764 | cmpObstruction->SetMovingFlag(false); |
769 | | StartSucceeded(); |
| 766 | m_PathState = PATHSTATE_FOLLOWING_REQUESTING_SHORT; |
| 767 | |
| 768 | // With the new long pathfinder, the short pathfinder is used to get around units |
| 769 | // as those are not considered. This means we can effectively get stuck because of some units |
| 770 | // (sometimes the short pathfinder would have to go beyond its box to find a path and fails) |
| 771 | // While we wait for a better solution, we'll do two things: |
| 772 | // -Retry on the next turn: it might have been a moving unit so we'll be good to go |
| 773 | // -Tell idle units to go away. Hopefully that will clear a path. |
| 774 | |
| 775 | CmpPtr<ICmpRangeManager> cmpRangeManager(GetSystemEntity()); |
| 776 | CmpPtr<ICmpOwnership> cmpOwnership(GetEntityHandle()); |
| 777 | if (cmpRangeManager && cmpOwnership) |
| 778 | { |
| 779 | std::vector<int> Owners; |
| 780 | Owners.push_back(cmpOwnership->GetOwner()); |
| 781 | std::vector<entity_id_t> idleUnits = cmpRangeManager->ExecuteQueryAroundPos(cmpPosition->GetPosition2D(), entity_pos_t::Zero(), entity_pos_t::FromInt(10), Owners, IID_UnitMotion); |
| 782 | for (entity_id_t ent : idleUnits) |
| 783 | { |
| 784 | if (ent == GetEntityId()) |
| 785 | continue; |
| 786 | CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), ent); |
| 787 | if (cmpUnitMotion && !cmpUnitMotion->IsMoving()) |
| 788 | cmpUnitMotion->MoveToPointRange(cmpPosition->GetPosition2D().X, cmpPosition->GetPosition2D().Y, entity_pos_t::FromInt(10), entity_pos_t::FromInt(16)); |
| 789 | } |
| 790 | } |
| 791 | } |
797 | | else if (m_PathState == PATHSTATE_FOLLOWING_REQUESTING_SHORT) |
798 | | { |
799 | | // Replace the current path with the new one |
800 | | m_ShortPath = path; |
801 | | |
802 | | // If there's no waypoints then we couldn't get near the target |
803 | | if (m_ShortPath.m_Waypoints.empty()) |
804 | | { |
805 | | // We should stop moving (unless we're in a formation, in which |
806 | | // case we should continue following it) |
807 | | if (!IsFormationMember()) |
808 | | { |
809 | | MoveFailed(); |
810 | | return; |
811 | | } |
812 | | else |
813 | | { |
814 | | m_Moving = false; |
815 | | CMessageMotionChanged msg(false, true); |
816 | | GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); |
817 | | } |
818 | | } |
819 | | |
820 | | m_PathState = PATHSTATE_FOLLOWING; |
821 | | } |