mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-07-15 02:07:53 +07:00
Bugfixes
This commit is contained in:
@ -17,7 +17,7 @@ import mindustry.world.meta.*;
|
|||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
public class Pathfinder implements Runnable{
|
public class Pathfinder implements Runnable{
|
||||||
private static final long maxUpdate = Time.millisToNanos(4);
|
private static final long maxUpdate = Time.millisToNanos(6);
|
||||||
private static final int updateFPS = 60;
|
private static final int updateFPS = 60;
|
||||||
private static final int updateInterval = 1000 / updateFPS;
|
private static final int updateInterval = 1000 / updateFPS;
|
||||||
private static final int impassable = -1;
|
private static final int impassable = -1;
|
||||||
@ -37,6 +37,7 @@ public class Pathfinder implements Runnable{
|
|||||||
private ObjectMap<Position, PathTarget> targetCache = new ObjectMap<>();
|
private ObjectMap<Position, PathTarget> targetCache = new ObjectMap<>();
|
||||||
/** Current pathfinding thread */
|
/** Current pathfinding thread */
|
||||||
private @Nullable Thread thread;
|
private @Nullable Thread thread;
|
||||||
|
private IntArray tmpArray = new IntArray();
|
||||||
|
|
||||||
public Pathfinder(){
|
public Pathfinder(){
|
||||||
Events.on(WorldLoadEvent.class, event -> {
|
Events.on(WorldLoadEvent.class, event -> {
|
||||||
@ -198,14 +199,20 @@ public class Pathfinder implements Runnable{
|
|||||||
if(target.refreshRate() > 0 && Time.timeSinceMillis(data.lastUpdateTime) > target.refreshRate()){
|
if(target.refreshRate() > 0 && Time.timeSinceMillis(data.lastUpdateTime) > target.refreshRate()){
|
||||||
data.lastUpdateTime = Time.millis();
|
data.lastUpdateTime = Time.millis();
|
||||||
|
|
||||||
|
tmpArray.clear();
|
||||||
|
data.target.getPositions(data.team, tmpArray);
|
||||||
|
|
||||||
synchronized(data.targets){
|
synchronized(data.targets){
|
||||||
|
//make sure the position actually changed
|
||||||
|
if(!(data.targets.size == 1 && tmpArray.size == 1 && data.targets.first() == tmpArray.first())){
|
||||||
data.targets.clear();
|
data.targets.clear();
|
||||||
data.target.getPositions(data.team, data.targets);
|
data.target.getPositions(data.team, data.targets);
|
||||||
}
|
|
||||||
|
|
||||||
//queue an update
|
//queue an update
|
||||||
queue.post(() -> updateTargets(data));
|
queue.post(() -> updateTargets(data));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int[][] values = data.weights;
|
int[][] values = data.weights;
|
||||||
int value = values[tile.x][tile.y];
|
int value = values[tile.x][tile.y];
|
||||||
@ -279,7 +286,7 @@ public class Pathfinder implements Runnable{
|
|||||||
int tx = Point2.x(pos), ty = Point2.y(pos);
|
int tx = Point2.x(pos), ty = Point2.y(pos);
|
||||||
|
|
||||||
path.weights[tx][ty] = 0;
|
path.weights[tx][ty] = 0;
|
||||||
path.searches[tx][ty] = (short)path.search;
|
path.searches[tx][ty] = path.search;
|
||||||
path.frontier.addFirst(pos);
|
path.frontier.addFirst(pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -417,7 +424,7 @@ public class Pathfinder implements Runnable{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int refreshRate(){
|
public int refreshRate(){
|
||||||
return 1000 * 2;
|
return 900;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,7 +444,7 @@ public class Pathfinder implements Runnable{
|
|||||||
/** costs of getting to a specific tile */
|
/** costs of getting to a specific tile */
|
||||||
final int[][] weights;
|
final int[][] weights;
|
||||||
/** search IDs of each position - the highest, most recent search is prioritized and overwritten */
|
/** search IDs of each position - the highest, most recent search is prioritized and overwritten */
|
||||||
final short[][] searches;
|
final int[][] searches;
|
||||||
/** search frontier, these are Pos objects */
|
/** search frontier, these are Pos objects */
|
||||||
final IntQueue frontier = new IntQueue();
|
final IntQueue frontier = new IntQueue();
|
||||||
/** all target positions; these positions have a cost of 0, and must be synchronized on! */
|
/** all target positions; these positions have a cost of 0, and must be synchronized on! */
|
||||||
@ -452,7 +459,7 @@ public class Pathfinder implements Runnable{
|
|||||||
this.target = target;
|
this.target = target;
|
||||||
|
|
||||||
this.weights = new int[width][height];
|
this.weights = new int[width][height];
|
||||||
this.searches = new short[width][height];
|
this.searches = new int[width][height];
|
||||||
this.frontier.ensureCapacity((width + height) * 3);
|
this.frontier.ensureCapacity((width + height) * 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,11 @@ public class FormationAI extends AIController implements FormationMember{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(){
|
public void update(){
|
||||||
|
if(leader.dead()){
|
||||||
|
unit.resetController();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
unit.controlWeapons(leader.isRotate(), leader.isShooting());
|
unit.controlWeapons(leader.isRotate(), leader.isShooting());
|
||||||
// unit.moveAt(Tmp.v1.set(deltaX, deltaY).limit(unit.type().speed));
|
// unit.moveAt(Tmp.v1.set(deltaX, deltaY).limit(unit.type().speed));
|
||||||
if(leader.isShooting()){
|
if(leader.isShooting()){
|
||||||
@ -45,6 +50,11 @@ public class FormationAI extends AIController implements FormationMember{
|
|||||||
unit.moveAt(realtarget.sub(unit).limit(unit.type().speed));
|
unit.moveAt(realtarget.sub(unit).limit(unit.type().speed));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removed(Unitc unit){
|
||||||
|
formation.removeMember(this);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isBeingControlled(Unitc player){
|
public boolean isBeingControlled(Unitc player){
|
||||||
return leader == player;
|
return leader == player;
|
||||||
|
@ -71,6 +71,10 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
|||||||
return controller;
|
return controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void resetController(){
|
||||||
|
controller(type.createController());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void set(UnitType def, UnitController controller){
|
public void set(UnitType def, UnitController controller){
|
||||||
type(type);
|
type(type);
|
||||||
@ -125,6 +129,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
|||||||
@Override
|
@Override
|
||||||
public void remove(){
|
public void remove(){
|
||||||
teamIndex.updateCount(team(), -1);
|
teamIndex.updateCount(team(), -1);
|
||||||
|
controller.removed(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -15,6 +15,10 @@ public interface UnitController{
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default void removed(Unitc unit){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
default boolean isBeingControlled(Unitc player){
|
default boolean isBeingControlled(Unitc player){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,8 @@ public enum Binding implements KeyBind{
|
|||||||
pickupCargo(KeyCode.leftBracket),
|
pickupCargo(KeyCode.leftBracket),
|
||||||
dropCargo(KeyCode.rightBracket),
|
dropCargo(KeyCode.rightBracket),
|
||||||
|
|
||||||
|
command(KeyCode.g),
|
||||||
|
|
||||||
clear_building(KeyCode.q),
|
clear_building(KeyCode.q),
|
||||||
pause_building(KeyCode.e),
|
pause_building(KeyCode.e),
|
||||||
rotate(new Axis(KeyCode.scroll)),
|
rotate(new Axis(KeyCode.scroll)),
|
||||||
|
@ -4,7 +4,6 @@ import arc.*;
|
|||||||
import arc.Graphics.*;
|
import arc.Graphics.*;
|
||||||
import arc.Graphics.Cursor.*;
|
import arc.Graphics.Cursor.*;
|
||||||
import arc.graphics.g2d.*;
|
import arc.graphics.g2d.*;
|
||||||
import arc.input.*;
|
|
||||||
import arc.math.*;
|
import arc.math.*;
|
||||||
import arc.math.geom.*;
|
import arc.math.geom.*;
|
||||||
import arc.scene.*;
|
import arc.scene.*;
|
||||||
@ -211,31 +210,6 @@ public class DesktopInput extends InputHandler{
|
|||||||
Call.onUnitClear(player);
|
Call.onUnitClear(player);
|
||||||
controlledType = null;
|
controlledType = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO this is for debugging, remove later
|
|
||||||
if(Core.input.keyTap(KeyCode.g) && !player.dead() && player.unit() instanceof Commanderc){
|
|
||||||
Commanderc commander = (Commanderc)player.unit();
|
|
||||||
|
|
||||||
if(commander.isCommanding()){
|
|
||||||
commander.clearCommand();
|
|
||||||
}else{
|
|
||||||
|
|
||||||
FormationPattern pattern = new SquareFormation();
|
|
||||||
Formation formation = new Formation(new Vec3(player.x(), player.y(), player.unit().rotation()), pattern);
|
|
||||||
formation.slotAssignmentStrategy = new DistanceAssignmentStrategy(pattern);
|
|
||||||
|
|
||||||
units.clear();
|
|
||||||
|
|
||||||
Fx.commandSend.at(player);
|
|
||||||
Units.nearby(player.team(), player.x(), player.y(), 200f, u -> {
|
|
||||||
if(u.isAI()){
|
|
||||||
units.add(u);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
commander.command(formation, units);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!player.dead() && !state.isPaused() && !(Core.scene.getKeyboardFocus() instanceof TextField)){
|
if(!player.dead() && !state.isPaused() && !(Core.scene.getKeyboardFocus() instanceof TextField)){
|
||||||
@ -628,5 +602,33 @@ public class DesktopInput extends InputHandler{
|
|||||||
pay.dropLastPayload();
|
pay.dropLastPayload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(unit instanceof Commanderc){
|
||||||
|
Commanderc commander = (Commanderc)unit;
|
||||||
|
|
||||||
|
if(Core.input.keyTap(Binding.command)){
|
||||||
|
if(commander.isCommanding()){
|
||||||
|
commander.clearCommand();
|
||||||
|
}else{
|
||||||
|
FormationPattern pattern = new SquareFormation();
|
||||||
|
Formation formation = new Formation(new Vec3(player.x(), player.y(), player.unit().rotation()), pattern);
|
||||||
|
formation.slotAssignmentStrategy = new DistanceAssignmentStrategy(pattern);
|
||||||
|
|
||||||
|
units.clear();
|
||||||
|
|
||||||
|
Fx.commandSend.at(player);
|
||||||
|
Units.nearby(player.team(), player.x(), player.y(), 200f, u -> {
|
||||||
|
if(u.isAI()){
|
||||||
|
units.add(u);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
units.sort(u -> u.dst2(player.unit()));
|
||||||
|
units.truncate(unit.type().commandLimit);
|
||||||
|
|
||||||
|
commander.command(formation, units);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ public class UnitType extends UnlockableContent{
|
|||||||
public boolean canBoost = false;
|
public boolean canBoost = false;
|
||||||
public float sway = 1f;
|
public float sway = 1f;
|
||||||
public int payloadCapacity = 1;
|
public int payloadCapacity = 1;
|
||||||
|
public int commandLimit = 24;
|
||||||
|
|
||||||
public int legCount = 4;
|
public int legCount = 4;
|
||||||
public float legLength = 24f, legSpeed = 0.1f, legTrns = 1f;
|
public float legLength = 24f, legSpeed = 0.1f, legTrns = 1f;
|
||||||
|
Reference in New Issue
Block a user