Fixed unit movement regression caused by #11613 / Alternate unit mining effect (closes #12605)

This commit is contained in:
Anuken
2026-09-07 12:41:05 -04:00
parent 5a0c4bfc41
commit 85446f3284
3 changed files with 30 additions and 29 deletions
+25 -25
View File
@@ -17,7 +17,7 @@ import static mindustry.Vars.*;
public class CommandAI extends AIController{
protected static final int maxCommandQueueSize = 50, avoidInterval = 10;
protected static final Vec2 vecOut = new Vec2(), vecMovePos = new Vec2(), movePos = new Vec2();
protected static final Vec2 moveTarget = new Vec2(), offsetedDestination = new Vec2(), currentDestination = new Vec2();
protected static final UnitPayload tmpPayload = new UnitPayload(null);
protected static final int transferStateNone = 0, transferStateLoad = 1, transferStateUnload = 2;
@@ -276,31 +276,31 @@ public class CommandAI extends AIController{
if(targetPos != null){
boolean move = true, isFinalPoint = commandQueue.size == 0;
//workaround to let ground units pathfind into targeted solid payenter blocks
boolean isSolidPayload = false;
movePos.set(targetPos);
//actual final point that it needs to go to
currentDestination.set(targetPos);
targetBuild = world.buildWorld(targetPos.x, targetPos.y);
if(unit.isGrounded() && targetBuild != null && targetBuild.tile.solid() && targetBuild.block.acceptsUnitPayloads && unit.type.pathCostId != ControlPathfinder.costIdLegs && !ramming){
Tile best = targetBuild.findClosestEdge(unit, Tile::solid);
if(best != null){
movePos.set(best);
isSolidPayload = true;
currentDestination.set(best);
}
}
vecOut.set(movePos);
vecMovePos.set(movePos);
//target straight-line point it is currently moving to; can include pathfinding sub-waypoints
moveTarget.set(currentDestination);
//destination + formation offset
offsetedDestination.set(currentDestination);
//the enter payload command requires an exact position
if(group != null && group.valid && groupIndex < group.units.size && command != UnitCommand.enterPayloadCommand){
vecMovePos.add(group.positions[groupIndex * 2], group.positions[groupIndex * 2 + 1]);
offsetedDestination.add(group.positions[groupIndex * 2], group.positions[groupIndex * 2 + 1]);
}
Building targetBuild = world.buildWorld(targetPos.x, targetPos.y);
if(
(hasStance(UnitStance.patrol) && !hasStance(UnitStance.pursueTarget) && target != null && unit.within(target, unit.type.range - 2f) && !unit.type.circleTarget) ||
(command == UnitCommand.enterPayloadCommand && unit.within(movePos, 4f) || (targetBuild != null && !unit.type.circleTarget && unit.within(targetBuild, targetBuild.block.size * tilesize/2f * 0.9f))) ||
(command == UnitCommand.loopPayloadCommand && unit.within(vecMovePos, 10f))
(command == UnitCommand.enterPayloadCommand && unit.within(currentDestination, 4f) || (targetBuild != null && !unit.type.circleTarget && unit.within(targetBuild, targetBuild.block.size * tilesize/2f * 0.9f))) ||
(command == UnitCommand.loopPayloadCommand && unit.within(offsetedDestination, 10f))
){
move = false;
}
@@ -339,27 +339,27 @@ public class CommandAI extends AIController{
//TODO maybe stop moving too?
if(withinAttackRange){
move = true;
vecOut.set(vecMovePos);
moveTarget.set(offsetedDestination);
}else{
var result = controlPath.getPathPosition(unit, movePos, isSolidPayload ? movePos : targetPos);
var result = controlPath.getPathPosition(unit, offsetedDestination, currentDestination);
unreachable = result.unreachable;
move &= result.move && (!blockingUnit || timeSpentBlocked > maxBlockTime);
if(result.move) vecOut.set(result.dest);
if(result.move) moveTarget.set(result.dest);
//do not wiggle in place
if(unit.type.naval && result.next != null && !unit.canPass(result.next.x, result.next.y) && move && unit.tileOn() == world.tileWorld(vecOut.x, vecOut.y)){
if(unit.type.naval && result.next != null && !unit.canPass(result.next.x, result.next.y) && move && unit.tileOn() == world.tileWorld(moveTarget.x, moveTarget.y)){
move = false;
}
}
//rare case where unit must be perfectly aligned (happens with 1-tile gaps)
alwaysArrive = vecOut.epsilonEquals(unit.tileX() * tilesize, unit.tileY() * tilesize);
alwaysArrive = moveTarget.epsilonEquals(unit.tileX() * tilesize, unit.tileY() * tilesize);
//we've reached the final point if the returned coordinate is equal to the supplied input
isFinalPoint &= vecMovePos.epsilonEquals(vecOut, 4.1f);
isFinalPoint &= offsetedDestination.epsilonEquals(moveTarget, 4.1f);
//if the path is invalid, stop trying and record the end as unreachable
if(unit.team.isAI() && (unreachable || unit.isPathImpassable(World.toTile(vecMovePos.x), World.toTile(vecMovePos.y)))){
if(unit.team.isAI() && (unreachable || unit.isPathImpassable(World.toTile(offsetedDestination.x), World.toTile(offsetedDestination.y)))){
if(attackTarget instanceof Building build){
unreachableBuildings.addUnique(build.pos());
}
@@ -368,7 +368,7 @@ public class CommandAI extends AIController{
return;
}
}else{
vecOut.set(vecMovePos);
moveTarget.set(offsetedDestination);
}
if(command == UnitCommand.loopPayloadCommand){
@@ -380,7 +380,7 @@ public class CommandAI extends AIController{
target = attackTarget;
circleAttack(unit.type.circleTargetRadius);
}else{
moveTo(vecOut,
moveTo(moveTarget,
withinAttackRange ? engageRange :
unit.isGrounded() ? 0f :
attackTarget != null && !ramming ? engageRange : 0f,
@@ -394,20 +394,20 @@ public class CommandAI extends AIController{
}
if(unit.isFlying() && move && !(unit.type.circleTarget && !unit.type.omniMovement) && (attackTarget == null || !unit.within(attackTarget, unit.type.range))){
unit.lookAt(vecMovePos);
unit.lookAt(offsetedDestination);
}else{
faceTarget();
}
//reached destination, end pathfinding
if(attackTarget == null && (unit.within(vecMovePos, command.exactArrival && commandQueue.size == 0 ? 1f : Math.max(5f, unit.hitSize / 2f)) ||
if(attackTarget == null && (unit.within(offsetedDestination, command.exactArrival && commandQueue.size == 0 ? 1f : Math.max(5f, unit.hitSize / 2f)) ||
//for circling units, it doesn't need to reach the exact waypoint.
(!unit.type.omniMovement && unit.type.flying && !unit.type.rotateMoveFirst && !command.exactArrival && Angles.angleDist(unit.angleTo(vecMovePos), unit.rotation) > 60f &&
unit.within(vecMovePos, Math.min(50f, 360f / unit.type.rotateSpeed * unit.type.speed / (Mathf.pi * 2f)))))){
(!unit.type.omniMovement && unit.type.flying && !unit.type.rotateMoveFirst && !command.exactArrival && Angles.angleDist(unit.angleTo(offsetedDestination), unit.rotation) > 60f &&
unit.within(offsetedDestination, Math.min(50f, 360f / unit.type.rotateSpeed * unit.type.speed / (Mathf.pi * 2f)))))){
finishPath();
}
if(stopWhenInRange && targetPos != null && unit.within(vecMovePos, engageRange * 0.9f)){
if(stopWhenInRange && targetPos != null && unit.within(offsetedDestination, engageRange * 0.9f)){
finishPath();
stopWhenInRange = false;
}
@@ -85,10 +85,11 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc{
mineTile = null;
mineTimer = 0f;
}else if(mining() && item != null){
mineTimer += Time.delta * type.mineSpeed * state.rules.unitMineSpeed(team());
float rate = Time.delta * type.mineSpeed * state.rules.unitMineSpeed(team());
mineTimer += rate;
if(Mathf.chance(0.08 * Time.delta)){
Fx.unitMine.at(mineTile.worldx() + Mathf.range(tilesize / 2f), mineTile.worldy() + Mathf.range(tilesize / 2f), 0f, item.color);
if(Mathf.chance(0.035f * rate)){
Fx.unitMine.at(mineTile.worldx() + Mathf.range(2f), mineTile.worldy() + Mathf.range(2f), 0f, item.color);
}
if(mineTimer >= 50f + (type.mineHardnessScaling ? item.hardness*15f : 15f)){
+1 -1
View File
@@ -26,4 +26,4 @@ org.gradle.caching=true
org.gradle.internal.http.socketTimeout=100000
org.gradle.internal.http.connectionTimeout=100000
android.enableR8.fullMode=false
archash=c4c3707ae8
archash=3eb7d633a3