/** ** Returns the next element of a path. ** ** @param unit Unit that wants the path element. ** @param pxd Pointer for the x direction. ** @param pyd Pointer for the y direction. ** ** @pre The unit's field flags must have been unmarked ** on the map; see UnmarkUnitFieldFlags. ** ** @return >0 remaining path length, 0 wait for path, -1 ** reached goal, -2 can't reach the goal. */ int NextPathElement(CUnit *unit, int *pxd, int *pyd) { int result; // Please use UnmarkUnitFieldFlags and MarkUnitFieldFlags // around NextPathElement calls. Assert((Map.Field(unit->X, unit->Y)->Flags & unit->Type->FieldFlags) == 0); // Attempt to use path cache // FIXME: If there is a goal, it may have moved, ruining the cache *pxd = 0; *pyd = 0; // Goal has moved, need to recalculate path or no cached path if (unit->Data.Move.Length <= 0 || (unit->Orders[0]->Goal && (unit->Orders[0]->Goal->X != unit->Orders[0]->X || unit->Orders[0]->Goal->Y != unit->Orders[0]->Y))) { result = NewPath(unit); if (result == PF_UNREACHABLE) { unit->Data.Move.Length = 0; return result; } if (result == PF_REACHED) { return result; } if (unit->Goal) { // Update Orders unit->Orders[0]->X = unit->Goal->X; unit->Orders[0]->Y = unit->Goal->Y; } } *pxd = Heading2X[(int)unit->Data.Move.Path[(int)unit->Data.Move.Length - 1]]; *pyd = Heading2Y[(int)unit->Data.Move.Path[(int)unit->Data.Move.Length - 1]]; result = unit->Data.Move.Length; unit->Data.Move.Length--; if (!UnitCanBeAt(unit, *pxd + unit->X, *pyd + unit->Y)) { // If obstructing unit is moving, wait for a bit. if (unit->Data.Move.Fast) { unit->Data.Move.Fast--; AstarDebugPrint("WAIT at %d\n" _C_ unit->Data.Move.Fast); result = PF_WAIT; } else { unit->Data.Move.Fast = 10; AstarDebugPrint("SET WAIT to 10\n"); result = PF_WAIT; } if (unit->Data.Move.Fast == 0 && result != 0) { AstarDebugPrint("WAIT expired\n"); result = NewPath(unit); if (result > 0) { *pxd = Heading2X[(int)unit->Data.Move.Path[(int)unit->Data.Move.Length - 1]]; *pyd = Heading2Y[(int)unit->Data.Move.Path[(int)unit->Data.Move.Length - 1]]; if (!UnitCanBeAt(unit, *pxd + unit->X, *pyd + unit->Y)) { // There may be unit in the way, Astar may allow you to walk onto it. result = PF_UNREACHABLE; *pxd = 0; *pyd = 0; } else { result = unit->Data.Move.Length; unit->Data.Move.Length--; } } } } if (result != PF_WAIT) { unit->Data.Move.Fast = 0; } return result; }
/** ** Returns the next element of a path. ** ** @param unit Unit that wants the path element. ** @param pxd Pointer for the x direction. ** @param pyd Pointer for the y direction. ** ** @return >0 remaining path length, 0 wait for path, -1 ** reached goal, -2 can't reach the goal. */ int NextPathElement(CUnit &unit, short int *pxd, short int *pyd) { PathFinderInput &input = unit.pathFinderData->input; PathFinderOutput &output = unit.pathFinderData->output; unit.CurrentOrder()->UpdatePathFinderData(input); // Attempt to use path cache // FIXME: If there is a goal, it may have moved, ruining the cache *pxd = 0; *pyd = 0; // Goal has moved, need to recalculate path or no cached path if (output.Length <= 0 || input.IsRecalculateNeeded()) { const int result = NewPath(input, output); if (result == PF_UNREACHABLE) { output.Length = 0; return result; } if (result == PF_REACHED) { return result; } } *pxd = Heading2X[(int)output.Path[(int)output.Length - 1]]; *pyd = Heading2Y[(int)output.Path[(int)output.Length - 1]]; const Vec2i dir(*pxd, *pyd); int result = output.Length; output.Length--; if (!UnitCanBeAt(unit, unit.tilePos + dir)) { // If obstructing unit is moving, wait for a bit. if (output.Fast) { output.Fast--; AstarDebugPrint("WAIT at %d\n" _C_ output.Fast); result = PF_WAIT; } else { output.Fast = 10; AstarDebugPrint("SET WAIT to 10\n"); result = PF_WAIT; } if (output.Fast == 0 && result != 0) { AstarDebugPrint("WAIT expired\n"); result = NewPath(input, output); if (result > 0) { *pxd = Heading2X[(int)output.Path[(int)output.Length - 1]]; *pyd = Heading2Y[(int)output.Path[(int)output.Length - 1]]; if (!UnitCanBeAt(unit, unit.tilePos + dir)) { // There may be unit in the way, Astar may allow you to walk onto it. result = PF_UNREACHABLE; *pxd = 0; *pyd = 0; } else { result = output.Length; output.Length--; } } } } if (result != PF_WAIT) { output.Fast = 0; } return result; }