port depot finder change from Wyrmgus that searches from outside mine
This commit is contained in:
parent
f454ad3227
commit
02b70a362b
6 changed files with 69 additions and 41 deletions
src
action
ai
include
pathfinder
unit
|
@ -910,20 +910,19 @@ int COrder_Resource::StopGathering(CUnit &unit)
|
|||
|
||||
// Find and send to resource deposit.
|
||||
CUnit *depot = FindDeposit(unit, 1000, unit.CurrentResource);
|
||||
// There's a bug in the traversal that leads to workers "sometimes" not finding their way to the old depot
|
||||
// TODO: once we figure out that bug, this workaround can probably be removed.
|
||||
// There's a bug in the traversal that leads to workers "sometimes" not finding their way to the old depot.
|
||||
// timfel: of course, maybe it's actually nice that workers drop out towards their last depot...
|
||||
if (!depot && (!(resinfo.HarvestFromOutside || resinfo.TerrainHarvester)) && Depot && Depot->IsAlive()) {
|
||||
CUnit *depot = FindDeposit(unit, 1000, unit.CurrentResource);
|
||||
Assert(unit.Container);
|
||||
DropOutNearest(unit, Depot->tilePos + depot->Type->GetHalfTileSize(), source);
|
||||
// try to path again
|
||||
depot = FindDeposit(unit, 1000, unit.CurrentResource);
|
||||
DropOutNearest(unit, Depot->tilePos + Depot->Type->GetHalfTileSize(), source);
|
||||
}
|
||||
Depot = depot;
|
||||
if (!depot || !unit.ResourcesHeld || this->Finished) {
|
||||
if (!(resinfo.HarvestFromOutside || resinfo.TerrainHarvester)) {
|
||||
Assert(unit.Container);
|
||||
DropOutOnSide(unit, LookingW, source);
|
||||
if (unit.Container) {
|
||||
DropOutOnSide(unit, LookingW, source);
|
||||
}
|
||||
}
|
||||
CUnit *mine = this->Resource.Mine;
|
||||
|
||||
|
|
|
@ -926,7 +926,7 @@ void AiCanNotMove(CUnit &unit)
|
|||
const int gh = unit.pathFinderData->input.GetGoalSize().y;
|
||||
|
||||
AiPlayer = unit.Player->Ai;
|
||||
if (PlaceReachable(unit, goalPos, gw, gh, 0, 255)) {
|
||||
if (PlaceReachable(unit, goalPos, gw, gh, 0, 255, false)) {
|
||||
// Path probably closed by unit here
|
||||
AiMoveUnitInTheWay(unit);
|
||||
}
|
||||
|
|
|
@ -219,13 +219,13 @@ extern void FreePathfinder();
|
|||
/// Returns the next element of the path
|
||||
extern int NextPathElement(CUnit &unit, short int *xdp, short int *ydp);
|
||||
/// Return path length to unit 'dst'.
|
||||
extern int UnitReachable(const CUnit &src, const CUnit &dst, int range);
|
||||
extern int UnitReachable(const CUnit &src, const CUnit &dst, int range, bool from_outside_container);
|
||||
/// Return path length to unit 'dst' or error code.
|
||||
extern int CalcPathLengthToUnit(const CUnit &src, const CUnit &dst,
|
||||
const int minrange, const int range);
|
||||
/// Can the unit 'src' reach the place x,y
|
||||
extern int PlaceReachable(const CUnit &src, const Vec2i &pos, int w, int h,
|
||||
int minrange, int maxrange);
|
||||
int minrange, int maxrange, bool from_outside_container);
|
||||
|
||||
//
|
||||
// in astar.cpp
|
||||
|
|
|
@ -183,33 +183,68 @@ void FreePathfinder()
|
|||
**
|
||||
** @return Distance to place.
|
||||
*/
|
||||
int PlaceReachable(const CUnit &src, const Vec2i &goalPos, int w, int h, int minrange, int range)
|
||||
int PlaceReachable(const CUnit &src, const Vec2i &goalPos, int w, int h, int minrange, int range, bool from_outside_container)
|
||||
{
|
||||
SetAStarFixedEnemyUnitsUnpassable(true); /// change Path Finder setting to don't count tiles with enemy units as passable
|
||||
int i = AStarFindPath(src.tilePos, goalPos, w, h,
|
||||
src.Type->TileWidth, src.Type->TileHeight,
|
||||
minrange, range, NULL, 0, src);
|
||||
int i;
|
||||
Vec2i srcTilePos = src.tilePos;
|
||||
int srcTW = src.Type->TileWidth;
|
||||
int srcTH = src.Type->TileHeight;
|
||||
if (!from_outside_container || !src.Container) {
|
||||
i = AStarFindPath(srcTilePos, goalPos, w, h,
|
||||
srcTW, srcTH,
|
||||
minrange, range, nullptr, 0, src);
|
||||
} else {
|
||||
const CUnit *first_container = GetFirstContainer(src);
|
||||
|
||||
const Vec2i offset(1, 1);
|
||||
int containerW = first_container->Type->TileWidth;
|
||||
int containerH = first_container->Type->TileHeight;
|
||||
Vec2i containerTilePos = first_container->tilePos;
|
||||
// check top and bottom rows and left and right columns around the container
|
||||
for (int x = -1; x <= containerW; x++) {
|
||||
for (int y = -1; y <= containerH; y++) {
|
||||
if (x >= 0 && x < containerW && y >= 0 && y < containerH) {
|
||||
// inside the container, no need to check
|
||||
continue;
|
||||
}
|
||||
Vec2i tile_pos = containerTilePos + Vec2i(x, y);
|
||||
if (!Map.Info.IsPointOnMap(tile_pos)) {
|
||||
continue;
|
||||
}
|
||||
if (!CanMoveToMask(tile_pos, src.Type->MovementMask)) {
|
||||
//ignore tiles to which the unit cannot be dropped from its container
|
||||
continue;
|
||||
}
|
||||
|
||||
i = AStarFindPath(tile_pos, goalPos, w, h,
|
||||
srcTW, srcTH,
|
||||
minrange, range, nullptr, 0, src);
|
||||
|
||||
switch (i) {
|
||||
case PF_FAILED:
|
||||
case PF_UNREACHABLE:
|
||||
case PF_WAIT:
|
||||
continue;
|
||||
}
|
||||
goto finished;
|
||||
}
|
||||
}
|
||||
}
|
||||
finished:
|
||||
SetAStarFixedEnemyUnitsUnpassable(false); /// restore Path Finder setting
|
||||
switch (i) {
|
||||
case PF_FAILED:
|
||||
case PF_UNREACHABLE:
|
||||
i = 0;
|
||||
break;
|
||||
case PF_WAIT:
|
||||
return 0;
|
||||
case PF_REACHED:
|
||||
/* since most of this function usage check return value as bool
|
||||
* then reached state should be track as true value */
|
||||
i = 1;
|
||||
break;
|
||||
case PF_WAIT:
|
||||
Assert(0);
|
||||
i = 0;
|
||||
break;
|
||||
case PF_MOVE:
|
||||
break;
|
||||
* then reached state should be track as true value */
|
||||
return std::max(i, 1);
|
||||
default:
|
||||
break;
|
||||
return i;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -221,14 +256,14 @@ int PlaceReachable(const CUnit &src, const Vec2i &goalPos, int w, int h, int min
|
|||
**
|
||||
** @return Distance to place.
|
||||
*/
|
||||
int UnitReachable(const CUnit &src, const CUnit &dst, int range)
|
||||
int UnitReachable(const CUnit &src, const CUnit &dst, int range, bool from_outside_container)
|
||||
{
|
||||
// Find a path to the goal.
|
||||
if (src.Type->Building) {
|
||||
return 0;
|
||||
}
|
||||
const int depth = PlaceReachable(src, dst.tilePos,
|
||||
dst.Type->TileWidth, dst.Type->TileHeight, 0, range);
|
||||
dst.Type->TileWidth, dst.Type->TileHeight, 0, range, from_outside_container);
|
||||
if (depth <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -2984,7 +2984,7 @@ static void HitUnit_AttackBack(CUnit &attacker, CUnit &target)
|
|||
COrder_Attack &order = dynamic_cast<COrder_Attack &>(*target.CurrentOrder());
|
||||
if (order.IsAutoTargeting() || target.Player->AiEnabled) {
|
||||
if (attacker.IsVisibleAsGoal(*target.Player)) {
|
||||
if (UnitReachable(target, attacker, target.Stats->Variables[ATTACKRANGE_INDEX].Max)) {
|
||||
if (UnitReachable(target, attacker, target.Stats->Variables[ATTACKRANGE_INDEX].Max, false)) {
|
||||
target.UnderAttack = underAttack; /// allow target to ignore non aggressive targets while searching attacker
|
||||
order.OfferNewTarget(target, &attacker);
|
||||
}
|
||||
|
@ -3018,7 +3018,7 @@ static void HitUnit_AttackBack(CUnit &attacker, CUnit &target)
|
|||
const Vec2i posToAttack = (attacker.IsVisibleAsGoal(*target.Player))
|
||||
? attacker.tilePos
|
||||
: GetRndPosInDirection(target.tilePos, attacker.tilePos, false, target.Type->ReactRangeComputer, 2);
|
||||
if (!PlaceReachable(target, posToAttack, 1, 1, 0, target.Stats->Variables[ATTACKRANGE_INDEX].Max)) {
|
||||
if (!PlaceReachable(target, posToAttack, 1, 1, 0, target.Stats->Variables[ATTACKRANGE_INDEX].Max, false)) {
|
||||
return;
|
||||
}
|
||||
COrder *savedOrder = NULL;
|
||||
|
|
|
@ -213,14 +213,8 @@ class BestDepotFinder
|
|||
return;
|
||||
}
|
||||
|
||||
// calck real travel distance
|
||||
if (worker->Container != nullptr) {
|
||||
UnmarkUnitFieldFlags(*first_container);
|
||||
}
|
||||
const int travel_distance = UnitReachable(*worker, *dest, 1);
|
||||
if (worker->Container != nullptr) {
|
||||
MarkUnitFieldFlags(*first_container);
|
||||
}
|
||||
// calc real travel distance
|
||||
const int travel_distance = UnitReachable(*worker, *dest, 1, worker->Container != nullptr);
|
||||
//
|
||||
// Take this depot?
|
||||
//
|
||||
|
@ -730,7 +724,7 @@ private:
|
|||
// Unit in range ?
|
||||
const int d = attacker->MapDistanceTo(*dest);
|
||||
|
||||
if (d > attackrange && !UnitReachable(*attacker, *dest, attackrange)) {
|
||||
if (d > attackrange && !UnitReachable(*attacker, *dest, attackrange, false)) {
|
||||
return INT_MAX;
|
||||
}
|
||||
|
||||
|
@ -934,7 +928,7 @@ public:
|
|||
|
||||
int attackrange = attacker->Stats->Variables[ATTACKRANGE_INDEX].Max;
|
||||
if (d <= attackrange ||
|
||||
(d <= range && UnitReachable(*attacker, *dest, attackrange))) {
|
||||
(d <= range && UnitReachable(*attacker, *dest, attackrange, false))) {
|
||||
++enemy_count;
|
||||
} else {
|
||||
dest->CacheLock = 1;
|
||||
|
|
Loading…
Add table
Reference in a new issue