diff --git a/core/src/mindustry/ai/ControlPathfinder.java b/core/src/mindustry/ai/ControlPathfinder.java index f50345a554..fe9f528384 100644 --- a/core/src/mindustry/ai/ControlPathfinder.java +++ b/core/src/mindustry/ai/ControlPathfinder.java @@ -1101,7 +1101,9 @@ public class ControlPathfinder implements Runnable{ //cache raycast results to run every time the world updates, and every tile the unit crosses if(lastRaycastTile != packedPos){ //near the destination, standard raycasting tends to break down, so use the more permissive 'near' variant that doesn't take into account edges of walls - raycastResult = unit.within(destination, tilesize * 2.5f) ? !raycastRect(unit.x, unit.y, destination.x, destination.y, team, cost, tileX, tileY, actualDestX, actualDestY, tileRectSize) : !raycast(team, cost, tileX, tileY, actualDestX, actualDestY); + raycastResult = unit.within(destination, tilesize * 2.5f) ? + !raycastRect(unit.x, unit.y, destination.x, destination.y, team, cost, tileX, tileY, actualDestX, actualDestY, tileRectSize) : + !raycast(team, cost, tileX, tileY, actualDestX, actualDestY); if(request != null){ request.lastRaycastTile = packedPos; @@ -1141,7 +1143,7 @@ public class ControlPathfinder implements Runnable{ boolean recalc = false; //TODO last pos can change if the flowfield changes. - if(initialTileOn.pos() != request.lastTile || request.lastTargetTile == null){ + if(initialTileOn.pos() != request.lastTile || request.lastTargetTile == null || true){ boolean anyNearSolid = false; //find the next tile until one near a solid block is discovered @@ -1176,7 +1178,7 @@ public class ControlPathfinder implements Runnable{ if(!(current == null || (costId == costIdGround && current.dangerous() && !tileOn.dangerous()))){ //when anyNearSolid is false, no solid tiles have been encountered anywhere so far, so raycasting is a waste of time - if(anyNearSolid && !tileOn.dangerous() && raycastRect(unit.x, unit.y, current.x * tilesize, current.y * tilesize, team, cost, initialTileOn.x, initialTileOn.y, current.x, current.y, tileRectSize)){ + if(anyNearSolid && !(tileOn.dangerous() && costId == costIdGround) && raycastRect(unit.x, unit.y, current.x * tilesize, current.y * tilesize, team, cost, initialTileOn.x, initialTileOn.y, current.x, current.y, tileRectSize)){ //TODO this may be a mistake if(tileOn == initialTileOn){ @@ -1206,6 +1208,7 @@ public class ControlPathfinder implements Runnable{ } if(request.lastTargetTile != null){ + Fx.breakBlock.at(request.lastTargetTile.worldx(), request.lastTargetTile.worldy(), 1); out.set(request.lastTargetTile); request.lastTile = recalc ? -1 : initialTileOn.pos(); return true; diff --git a/core/src/mindustry/ai/types/CommandAI.java b/core/src/mindustry/ai/types/CommandAI.java index dec38c14ed..763916539a 100644 --- a/core/src/mindustry/ai/types/CommandAI.java +++ b/core/src/mindustry/ai/types/CommandAI.java @@ -205,6 +205,9 @@ public class CommandAI extends AIController{ boolean alwaysArrive = false; + float engageRange = unit.type.range - 10f; + boolean withinAttackRange = attackTarget != null && unit.within(attackTarget, engageRange) && stance != UnitStance.ram; + if(targetPos != null){ boolean move = true, isFinalPoint = commandQueue.size == 0; vecOut.set(targetPos); @@ -249,7 +252,16 @@ public class CommandAI extends AIController{ timeSpentBlocked = 0f; } - move = controlPath.getPathPosition(unit, vecMovePos, targetPos, vecOut, noFound) && (!blockingUnit || timeSpentBlocked > maxBlockTime); + //if the unit is next to the target, stop asking the pathfinder how to get there, it's a waste of CPU + //TODO maybe stop moving too? + if(withinAttackRange){ + move = true; + noFound[0] = false; + vecOut.set(vecMovePos); + }else{ + move = controlPath.getPathPosition(unit, vecMovePos, targetPos, vecOut, noFound) && (!blockingUnit || timeSpentBlocked > maxBlockTime); + } + //rare case where unit must be perfectly aligned (happens with 1-tile gaps) alwaysArrive = vecOut.epsilonEquals(unit.tileX() * tilesize, unit.tileY() * tilesize); //we've reached the final point if the returned coordinate is equal to the supplied input @@ -268,18 +280,16 @@ public class CommandAI extends AIController{ vecOut.set(vecMovePos); } - float engageRange = unit.type.range - 10f; - if(move){ if(unit.type.circleTarget && attackTarget != null){ target = attackTarget; circleAttack(80f); }else{ moveTo(vecOut, - attackTarget != null && unit.within(attackTarget, engageRange) && stance != UnitStance.ram ? engageRange : + withinAttackRange ? engageRange : unit.isGrounded() ? 0f : - attackTarget != null && stance != UnitStance.ram ? engageRange : - 0f, unit.isFlying() ? 40f : 100f, false, null, isFinalPoint || alwaysArrive); + attackTarget != null && stance != UnitStance.ram ? engageRange : 0f, + unit.isFlying() ? 40f : 100f, false, null, isFinalPoint || alwaysArrive); } }