Merge branch 'master' of https://github.com/Anuken/Mindustry into 7.0-features

This commit is contained in:
Anuken
2021-08-19 23:52:06 -04:00
32 changed files with 166 additions and 121 deletions

View File

@@ -78,13 +78,12 @@ schematic.tagexists = That tag already exists.
stats = Stats stats = Stats
stat.wave = Waves Defeated:[accent] {0} stat.wave = Waves Defeated:[accent] {0}
stat.unitsCreated = Units Created:[accent] {0}
stat.enemiesDestroyed = Enemies Destroyed:[accent] {0} stat.enemiesDestroyed = Enemies Destroyed:[accent] {0}
stat.built = Buildings Built:[accent] {0} stat.built = Buildings Built:[accent] {0}
stat.destroyed = Buildings Destroyed:[accent] {0} stat.destroyed = Buildings Destroyed:[accent] {0}
stat.deconstructed = Buildings Deconstructed:[accent] {0} stat.deconstructed = Buildings Deconstructed:[accent] {0}
stat.delivered = Resources Launched:
stat.playtime = Time Played:[accent] {0} stat.playtime = Time Played:[accent] {0}
stat.rank = Final Rank: [accent]{0}
globalitems = [accent]Total Items globalitems = [accent]Total Items
map.delete = Are you sure you want to delete the map "[accent]{0}[]"? map.delete = Are you sure you want to delete the map "[accent]{0}[]"?
@@ -385,6 +384,7 @@ waves.waves = wave(s)
waves.perspawn = per spawn waves.perspawn = per spawn
waves.shields = shields/wave waves.shields = shields/wave
waves.to = to waves.to = to
waves.max = max units
waves.guardian = Guardian waves.guardian = Guardian
waves.preview = Preview waves.preview = Preview
waves.edit = Edit... waves.edit = Edit...

Binary file not shown.

View File

@@ -202,15 +202,20 @@ public class BlockIndexer{
} }
public boolean eachBlock(@Nullable Team team, float wx, float wy, float range, Boolf<Building> pred, Cons<Building> cons){ public boolean eachBlock(@Nullable Team team, float wx, float wy, float range, Boolf<Building> pred, Cons<Building> cons){
breturnArray.clear();
if(team == null){ if(team == null){
returnBool = false;
allBuildings(wx, wy, range, b -> { allBuildings(wx, wy, range, b -> {
if(pred.get(b)){ if(pred.get(b)){
breturnArray.add(b); returnBool = true;
cons.get(b);
} }
}); });
return returnBool;
}else{ }else{
breturnArray.clear();
var buildings = team.data().buildings; var buildings = team.data().buildings;
if(buildings == null) return false; if(buildings == null) return false;
buildings.intersect(wx - range, wy - range, range*2f, range*2f, b -> { buildings.intersect(wx - range, wy - range, range*2f, range*2f, b -> {

View File

@@ -2,7 +2,6 @@ package mindustry.ai.types;
import arc.math.*; import arc.math.*;
import mindustry.ai.*; import mindustry.ai.*;
import mindustry.entities.*;
import mindustry.entities.units.*; import mindustry.entities.units.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.world.*; import mindustry.world.*;
@@ -49,13 +48,6 @@ public class GroundAI extends AIController{
unit.elevation = Mathf.approachDelta(unit.elevation, 0f, unit.type.riseSpeed); unit.elevation = Mathf.approachDelta(unit.elevation, 0f, unit.type.riseSpeed);
} }
if(!Units.invalidateTarget(target, unit, unit.range()) && unit.type.rotateShooting){ faceTarget();
if(unit.type.hasWeapons()){
unit.lookAt(Predict.intercept(unit, target, unit.type.weapons.first().bullet.speed));
}
}else if(unit.moving()){
unit.lookAt(unit.vel().angle());
}
} }
} }

View File

@@ -47,10 +47,10 @@ public class HugAI extends AIController{
})){ })){
if(unit.within(target, (unit.hitSize + (target instanceof Sized s ? s.hitSize() : 1f)) * 0.6f)){ if(unit.within(target, (unit.hitSize + (target instanceof Sized s ? s.hitSize() : 1f)) * 0.6f)){
//circle target //circle target
unit.moveAt(vec.set(target).sub(unit).rotate(90f).setLength(unit.speed())); unit.movePref(vec.set(target).sub(unit).rotate(90f).setLength(unit.speed()));
}else{ }else{
//move toward target in a straight line //move toward target in a straight line
unit.moveAt(vec.set(target).sub(unit).limit(unit.speed())); unit.movePref(vec.set(target).sub(unit).limit(unit.speed()));
} }
}else if(move){ }else if(move){
pathfind(Pathfinder.fieldCore); pathfind(Pathfinder.fieldCore);
@@ -69,13 +69,6 @@ public class HugAI extends AIController{
unit.elevation = Mathf.approachDelta(unit.elevation, 0f, unit.type.riseSpeed); unit.elevation = Mathf.approachDelta(unit.elevation, 0f, unit.type.riseSpeed);
} }
if(!Units.invalidateTarget(target, unit, unit.range()) && unit.type.rotateShooting){ faceTarget();
if(unit.type.hasWeapons()){
unit.lookAt(Predict.intercept(unit, target, unit.type.weapons.first().bullet.speed));
}
}else if(unit.moving()){
unit.lookAt(unit.vel().angle());
}
} }
} }

View File

@@ -41,10 +41,6 @@ public class SuicideAI extends GroundAI{
shoot = unit.within(target, unit.type.weapons.first().bullet.range() + shoot = unit.within(target, unit.type.weapons.first().bullet.range() +
(target instanceof Building b ? b.block.size * Vars.tilesize / 2f : ((Hitboxc)target).hitSize() / 2f)); (target instanceof Building b ? b.block.size * Vars.tilesize / 2f : ((Hitboxc)target).hitSize() / 2f));
if(unit.type.hasWeapons()){
unit.aimLook(Predict.intercept(unit, target, unit.type.weapons.first().bullet.speed));
}
//do not move toward walls or transport blocks //do not move toward walls or transport blocks
if(!(target instanceof Building build && !(build.block instanceof CoreBlock) && ( if(!(target instanceof Building build && !(build.block instanceof CoreBlock) && (
build.block.group == BlockGroup.walls || build.block.group == BlockGroup.walls ||
@@ -76,7 +72,7 @@ public class SuicideAI extends GroundAI{
if(!blocked){ if(!blocked){
moveToTarget = true; moveToTarget = true;
//move towards target directly //move towards target directly
unit.moveAt(vec.set(target).sub(unit).limit(unit.speed())); unit.movePref(vec.set(target).sub(unit).limit(unit.speed()));
} }
} }
} }
@@ -103,11 +99,11 @@ public class SuicideAI extends GroundAI{
pathfind(Pathfinder.fieldCore); pathfind(Pathfinder.fieldCore);
} }
} }
if(unit.moving()) unit.lookAt(unit.vel().angle());
} }
unit.controlWeapons(rotate, shoot); unit.controlWeapons(rotate, shoot);
faceTarget();
} }
@Override @Override

View File

@@ -164,7 +164,7 @@ public class StatusEffects implements ContentList{
}}; }};
boss = new StatusEffect("boss"){{ boss = new StatusEffect("boss"){{
color = Team.sharded.color; color = Team.crux.color;
permanent = true; permanent = true;
damageMultiplier = 1.3f; damageMultiplier = 1.3f;
healthMultiplier = 1.5f; healthMultiplier = 1.5f;

View File

@@ -172,13 +172,19 @@ public class Control implements ApplicationListener, Loadable{
Events.on(BlockDestroyEvent.class, e -> { Events.on(BlockDestroyEvent.class, e -> {
if(e.tile.team() == player.team()){ if(e.tile.team() == player.team()){
state.stats.buildingsDestroyed++; state.stats.buildingsDestroyed ++;
} }
}); });
Events.on(UnitDestroyEvent.class, e -> { Events.on(UnitDestroyEvent.class, e -> {
if(e.unit.team() != player.team()){ if(e.unit.team() != player.team()){
state.stats.enemyUnitsDestroyed++; state.stats.enemyUnitsDestroyed ++;
}
});
Events.on(UnitCreateEvent.class, e -> {
if(e.unit.team == state.rules.defaultTeam){
state.stats.unitsCreated++;
} }
}); });

View File

@@ -149,9 +149,17 @@ public abstract class UnlockableContent extends MappableContent{
} }
} }
public boolean unlockedNowHost(){
if(!state.isCampaign()) return true;
return net != null && net.client() ?
alwaysUnlocked || state.rules.researched.contains(name) :
unlocked || alwaysUnlocked;
}
public boolean unlocked(){ public boolean unlocked(){
if(net != null && net.client()) return alwaysUnlocked || state.rules.researched.contains(name); return net != null && net.client() ?
return unlocked || alwaysUnlocked; alwaysUnlocked || unlocked || state.rules.researched.contains(name) :
unlocked || alwaysUnlocked;
} }
/** Locks this content again. */ /** Locks this content again. */

View File

@@ -15,6 +15,8 @@ public class MapResizeDialog extends BaseDialog{
public MapResizeDialog(Intc2 cons){ public MapResizeDialog(Intc2 cons){
super("@editor.resizemap"); super("@editor.resizemap");
closeOnBack();
shown(() -> { shown(() -> {
cont.clear(); cont.clear();
width = editor.width(); width = editor.width();

View File

@@ -170,9 +170,8 @@ public class WaveInfoDialog extends BaseDialog{
t.remove(); t.remove();
updateWaves(); updateWaves();
}).pad(-6).size(46f).padRight(-12f); }).pad(-6).size(46f).padRight(-12f);
}, () -> showUpdate(group)).height(46f).pad(-6f).padBottom(0f); }, () -> showUpdate(group)).height(46f).pad(-6f).padBottom(0f).row();
t.row();
t.table(spawns -> { t.table(spawns -> {
spawns.field("" + (group.begin + 1), TextFieldFilter.digitsOnly, text -> { spawns.field("" + (group.begin + 1), TextFieldFilter.digitsOnly, text -> {
if(Strings.canParsePositiveInt(text)){ if(Strings.canParsePositiveInt(text)){
@@ -190,8 +189,8 @@ public class WaveInfoDialog extends BaseDialog{
updateWaves(); updateWaves();
} }
}).width(100f).get().setMessageText(""); }).width(100f).get().setMessageText("");
}); }).row();
t.row();
t.table(p -> { t.table(p -> {
p.add("@waves.every").padRight(4); p.add("@waves.every").padRight(4);
p.field(group.spacing + "", TextFieldFilter.digitsOnly, text -> { p.field(group.spacing + "", TextFieldFilter.digitsOnly, text -> {
@@ -201,9 +200,8 @@ public class WaveInfoDialog extends BaseDialog{
} }
}).width(100f); }).width(100f);
p.add("@waves.waves").padLeft(4); p.add("@waves.waves").padLeft(4);
}); }).row();
t.row();
t.table(a -> { t.table(a -> {
a.field(group.unitAmount + "", TextFieldFilter.digitsOnly, text -> { a.field(group.unitAmount + "", TextFieldFilter.digitsOnly, text -> {
if(Strings.canParsePositiveInt(text)){ if(Strings.canParsePositiveInt(text)){
@@ -220,8 +218,19 @@ public class WaveInfoDialog extends BaseDialog{
} }
}).width(80f); }).width(80f);
a.add("@waves.perspawn").padLeft(4); a.add("@waves.perspawn").padLeft(4);
}); }).row();
t.row();
t.table(a -> {
a.field(group.max + "", TextFieldFilter.digitsOnly, text -> {
if(Strings.canParsePositiveInt(text)){
group.max = Strings.parseInt(text);
updateWaves();
}
}).width(80f);
a.add("@waves.max").padLeft(5);
}).row();
t.table(a -> { t.table(a -> {
a.field((int)group.shields + "", TextFieldFilter.digitsOnly, text -> { a.field((int)group.shields + "", TextFieldFilter.digitsOnly, text -> {
if(Strings.canParsePositiveInt(text)){ if(Strings.canParsePositiveInt(text)){
@@ -238,9 +247,8 @@ public class WaveInfoDialog extends BaseDialog{
} }
}).width(80f); }).width(80f);
a.add("@waves.shields").padLeft(4); a.add("@waves.shields").padLeft(4);
}); }).row();
t.row();
t.check("@waves.guardian", b -> group.effect = (b ? StatusEffects.boss : null)).padTop(4).update(b -> b.setChecked(group.effect == StatusEffects.boss)).padBottom(8f); t.check("@waves.guardian", b -> group.effect = (b ? StatusEffects.boss : null)).padTop(4).update(b -> b.setChecked(group.effect == StatusEffects.boss)).padBottom(8f);
}).width(340f).pad(8); }).width(340f).pad(8);

View File

@@ -7,6 +7,7 @@ import arc.util.*;
import mindustry.*; import mindustry.*;
import mindustry.content.*; import mindustry.content.*;
import mindustry.entities.*; import mindustry.entities.*;
import mindustry.game.EventType.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.graphics.*; import mindustry.graphics.*;
import mindustry.type.*; import mindustry.type.*;
@@ -40,6 +41,7 @@ public class UnitSpawnAbility extends Ability{
Unit u = this.unit.create(unit.team); Unit u = this.unit.create(unit.team);
u.set(x, y); u.set(x, y);
u.rotation = unit.rotation; u.rotation = unit.rotation;
Events.fire(new UnitCreateEvent(u, null, unit));
if(!Vars.net.client()){ if(!Vars.net.client()){
u.add(); u.add();
} }

View File

@@ -76,6 +76,17 @@ abstract class MechComp implements Posc, Flyingc, Hitboxc, Unitc, Mechc, Elevati
return raw; return raw;
} }
@Override
@Replace
public void rotateMove(Vec2 vec){
//mechs use baseRotation to rotate, not rotation.
moveAt(Tmp.v2.trns(baseRotation, vec.len()));
if(!vec.isZero()){
baseRotation = Angles.moveToward(baseRotation, vec.angle(), type.rotateSpeed * Math.max(Time.delta, 1));
}
}
@Override @Override
public void moveAt(Vec2 vector, float acceleration){ public void moveAt(Vec2 vector, float acceleration){
//mark walking state when moving in a controlled manner //mark walking state when moving in a controlled manner

View File

@@ -51,6 +51,15 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
private transient boolean wasPlayer; private transient boolean wasPlayer;
private transient boolean wasHealed; private transient boolean wasHealed;
/** Move based on preferred unit movement type. */
public void movePref(Vec2 movement){
if(type.omniMovement){
moveAt(movement);
}else{
rotateMove(movement);
}
}
public void moveAt(Vec2 vector){ public void moveAt(Vec2 vector){
moveAt(vector, type.accel); moveAt(vector, type.accel);
} }

View File

@@ -76,6 +76,23 @@ public class AIController implements UnitController{
} }
} }
/** For ground units: Looks at the target, or the movement position. Does not apply to non-omni units. */
public void faceTarget(){
if(unit.type.omniMovement || unit instanceof Mechc){
if(!Units.invalidateTarget(target, unit, unit.range()) && unit.type.rotateShooting && unit.type.hasWeapons()){
unit.lookAt(Predict.intercept(unit, target, unit.type.weapons.first().bullet.speed));
}else if(unit.moving()){
unit.lookAt(unit.vel().angle());
}
}
}
public void faceMovement(){
if((unit.type.omniMovement || unit instanceof Mechc) && unit.moving()){
unit.lookAt(unit.vel().angle());
}
}
public boolean invalid(Teamc target){ public boolean invalid(Teamc target){
return Units.invalidateTarget(target, unit.team, unit.x, unit.y); return Units.invalidateTarget(target, unit.team, unit.x, unit.y);
} }
@@ -89,7 +106,7 @@ public class AIController implements UnitController{
if(tile == targetTile || (costType == Pathfinder.costNaval && !targetTile.floor().isLiquid)) return; if(tile == targetTile || (costType == Pathfinder.costNaval && !targetTile.floor().isLiquid)) return;
unit.moveAt(vec.trns(unit.angleTo(targetTile.worldx(), targetTile.worldy()), unit.speed())); unit.movePref(vec.trns(unit.angleTo(targetTile.worldx(), targetTile.worldy()), unit.speed()));
} }
public void updateWeapons(){ public void updateWeapons(){

View File

@@ -0,0 +1,25 @@
package mindustry.entities.units;
import arc.graphics.*;
import mindustry.graphics.*;
/** A sprite drawn in addition to the base unit sprites. */
public class UnitDecal{
public String region = "error";
public float x, y, rotation;
public float layer = Layer.flyingUnit + 1f;
public float xScale = 1f, yScale = 1f;
public Color color = Color.white;
public UnitDecal(String region, float x, float y, float rotation, float layer, Color color){
this.region = region;
this.x = x;
this.y = y;
this.rotation = rotation;
this.layer = layer;
this.color = color;
}
public UnitDecal(){
}
}

View File

@@ -411,14 +411,20 @@ public class EventType{
} }
} }
/** Called when a unit is created in a reconstructor or factory. */ /** Called when a unit is created in a reconstructor, factory or other unit. */
public static class UnitCreateEvent{ public static class UnitCreateEvent{
public final Unit unit; public final Unit unit;
public final Building spawner; public final @Nullable Building spawner;
public final @Nullable Unit spawnerUnit;
public UnitCreateEvent(Unit unit, Building spawner){ public UnitCreateEvent(Unit unit, Building spawner, Unit spawnerUnit){
this.unit = unit; this.unit = unit;
this.spawner = spawner; this.spawner = spawner;
this.spawnerUnit = spawnerUnit;
}
public UnitCreateEvent(Unit unit, Building spawner){
this(unit, spawner, null);
} }
} }

View File

@@ -1,52 +1,16 @@
package mindustry.game; package mindustry.game;
import arc.math.*;
import arc.struct.*;
import mindustry.type.*;
//TODO more stats:
//- units constructed
public class GameStats{ public class GameStats{
/** Total items delivered to global resoure counter. Campaign only. */
public ObjectIntMap<Item> itemsDelivered = new ObjectIntMap<>();
/** Enemy (red team) units destroyed. */ /** Enemy (red team) units destroyed. */
public int enemyUnitsDestroyed; public int enemyUnitsDestroyed;
/** Total waves lasted. */ /** Total waves lasted. */
public int wavesLasted; public int wavesLasted;
/** Total (ms) time lasted in this save/zone. */
public long timeLasted;
/** Friendly buildings fully built. */ /** Friendly buildings fully built. */
public int buildingsBuilt; public int buildingsBuilt;
/** Friendly buildings fully deconstructed. */ /** Friendly buildings fully deconstructed. */
public int buildingsDeconstructed; public int buildingsDeconstructed;
/** Friendly buildings destroyed. */ /** Friendly buildings destroyed. */
public int buildingsDestroyed; public int buildingsDestroyed;
/** Total units created by any means. */
//unused public int unitsCreated;
public RankResult calculateRank(Sector sector){
float score = 0;
int rankIndex = Mathf.clamp((int)score, 0, Rank.all.length - 1);
Rank rank = Rank.all[rankIndex];
String sign = Math.abs((rankIndex + 0.5f) - score) < 0.2f || rank.name().contains("S") ? "" : (rankIndex + 0.5f) < score ? "-" : "+";
return new RankResult(rank, sign);
}
public static class RankResult{
public final Rank rank;
/** + or - */
public final String modifier;
public RankResult(Rank rank, String modifier){
this.rank = rank;
this.modifier = modifier;
}
}
public enum Rank{
F, D, C, B, A, S, SS;
public static final Rank[] all = values();
}
} }

View File

@@ -29,7 +29,7 @@ public class MenuRenderer implements Disposable{
private float time = 0f; private float time = 0f;
private float flyerRot = 45f; private float flyerRot = 45f;
private int flyers = Mathf.chance(0.2) ? Mathf.random(35) : Mathf.random(15); private int flyers = Mathf.chance(0.2) ? Mathf.random(35) : Mathf.random(15);
private UnitType flyerType = content.units().select(u -> u.hitSize <= 20f && u.flying && u.onTitleScreen && u.region.found()).random(); private UnitType flyerType = content.units().select(u -> !u.isHidden() && u.hitSize <= 20f && u.flying && u.onTitleScreen && u.region.found()).random();
public MenuRenderer(){ public MenuRenderer(){
Time.mark(); Time.mark();

View File

@@ -642,11 +642,7 @@ public class DesktopInput extends InputHandler{
unit.lookAt(unit.prefRotation()); unit.lookAt(unit.prefRotation());
} }
if(omni){ unit.movePref(movement);
unit.moveAt(movement);
}else{
unit.rotateMove(movement);
}
unit.aim(unit.type.faceTarget ? Core.input.mouseWorld() : Tmp.v1.trns(unit.rotation, Core.input.mouseWorld().dst(unit)).add(unit.x, unit.y)); unit.aim(unit.type.faceTarget ? Core.input.mouseWorld() : Tmp.v1.trns(unit.rotation, Core.input.mouseWorld().dst(unit)).add(unit.x, unit.y));
unit.controlWeapons(true, player.shooting && !boosted); unit.controlWeapons(true, player.shooting && !boosted);

View File

@@ -919,11 +919,7 @@ public class MobileInput extends InputHandler implements GestureListener{
player.boosting = collisions.overlapsTile(rect) || !unit.within(targetPos, 85f); player.boosting = collisions.overlapsTile(rect) || !unit.within(targetPos, 85f);
if(omni){ unit.movePref(movement);
unit.moveAt(movement);
}else{
unit.rotateMove(movement);
}
//update shooting if not building + not mining //update shooting if not building + not mining
if(!player.unit().activelyBuilding() && player.unit().mineTile == null){ if(!player.unit().activelyBuilding() && player.unit().mineTile == null){

View File

@@ -447,7 +447,7 @@ public class LExecutor{
} }
} }
case build -> { case build -> {
if(state.rules.logicUnitBuild && unit.canBuild() && exec.obj(p3) instanceof Block block){ if(state.rules.logicUnitBuild && unit.canBuild() && exec.obj(p3) instanceof Block block && block.canBeBuilt()){
int x = World.toTile(x1 - block.offset/tilesize), y = World.toTile(y1 - block.offset/tilesize); int x = World.toTile(x1 - block.offset/tilesize), y = World.toTile(y1 - block.offset/tilesize);
int rot = exec.numi(p4); int rot = exec.numi(p4);

View File

@@ -77,6 +77,8 @@ public class UnitType extends UnlockableContent{
public Effect fallEffect = Fx.fallSmoke; public Effect fallEffect = Fx.fallSmoke;
public Effect fallThrusterEffect = Fx.fallSmoke; public Effect fallThrusterEffect = Fx.fallSmoke;
public Effect deathExplosionEffect = Fx.dynamicExplosion; public Effect deathExplosionEffect = Fx.dynamicExplosion;
/** Additional sprites that are drawn with the unit. */
public Seq<UnitDecal> decals = new Seq<>();
public Seq<Ability> abilities = new Seq<>(); public Seq<Ability> abilities = new Seq<>();
/** Flags to target based on priority. Null indicates that the closest target should be found. The closest enemy core is used as a fallback. */ /** Flags to target based on priority. Null indicates that the closest target should be found. The closest enemy core is used as a fallback. */
public BlockFlag[] targetFlags = {null}; public BlockFlag[] targetFlags = {null};
@@ -618,6 +620,18 @@ public class UnitType extends UnlockableContent{
unit.trns(-legOffset.x, -legOffset.y); unit.trns(-legOffset.x, -legOffset.y);
} }
if(decals.size > 0){
float base = unit.rotation - 90;
for(var d : decals){
Draw.z(d.layer);
Draw.scl(d.xScale, d.yScale);
Draw.color(d.color);
Draw.rect(d.region, unit.x + Angles.trnsx(base, d.x, d.y), unit.y + Angles.trnsy(base, d.x, d.y), base + d.rotation);
}
Draw.reset();
Draw.z(z);
}
if(unit.abilities.size > 0){ if(unit.abilities.size > 0){
for(Ability a : unit.abilities){ for(Ability a : unit.abilities){
Draw.reset(); Draw.reset();
@@ -911,4 +925,5 @@ public class UnitType extends UnlockableContent{
} }
//endregion //endregion
} }

View File

@@ -4,7 +4,6 @@ import arc.*;
import mindustry.core.GameState.*; import mindustry.core.GameState.*;
import mindustry.game.EventType.*; import mindustry.game.EventType.*;
import mindustry.game.*; import mindustry.game.*;
import mindustry.type.*;
import static mindustry.Vars.*; import static mindustry.Vars.*;
@@ -52,6 +51,7 @@ public class GameOverDialog extends BaseDialog{
t.margin(13f); t.margin(13f);
t.left().defaults().left(); t.left().defaults().left();
t.add(Core.bundle.format("stat.wave", state.stats.wavesLasted)).row(); t.add(Core.bundle.format("stat.wave", state.stats.wavesLasted)).row();
t.add(Core.bundle.format("stat.unitsCreated", state.stats.unitsCreated)).row();
t.add(Core.bundle.format("stat.enemiesDestroyed", state.stats.enemyUnitsDestroyed)).row(); t.add(Core.bundle.format("stat.enemiesDestroyed", state.stats.enemyUnitsDestroyed)).row();
t.add(Core.bundle.format("stat.built", state.stats.buildingsBuilt)).row(); t.add(Core.bundle.format("stat.built", state.stats.buildingsBuilt)).row();
t.add(Core.bundle.format("stat.destroyed", state.stats.buildingsDestroyed)).row(); t.add(Core.bundle.format("stat.destroyed", state.stats.buildingsDestroyed)).row();
@@ -59,17 +59,6 @@ public class GameOverDialog extends BaseDialog{
if(control.saves.getCurrent() != null){ if(control.saves.getCurrent() != null){
t.add(Core.bundle.format("stat.playtime", control.saves.getCurrent().getPlayTime())).row(); t.add(Core.bundle.format("stat.playtime", control.saves.getCurrent().getPlayTime())).row();
} }
if(state.isCampaign() && !state.stats.itemsDelivered.isEmpty()){
t.add("@stat.delivered").row();
for(Item item : content.items()){
if(state.stats.itemsDelivered.get(item, 0) > 0){
t.table(items -> {
items.add(" [lightgray]" + state.stats.itemsDelivered.get(item, 0));
items.image(item.uiIcon).size(8 * 3).pad(4);
}).left().row();
}
}
}
if(state.isCampaign() && net.client()){ if(state.isCampaign() && net.client()){
t.add("@gameover.waiting").padTop(20f).row(); t.add("@gameover.waiting").padTop(20f).row();

View File

@@ -540,7 +540,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
//sector notifications & search //sector notifications & search
c.top().right(); c.top().right();
c.defaults().width(280f); c.defaults().width(290f);
c.button(bundle.get("sectorlist") + c.button(bundle.get("sectorlist") +
(attacked == 0 ? "" : "\n[red]⚠[lightgray] " + bundle.format("sectorlist.attacked", "[red]" + attacked + "[]")), (attacked == 0 ? "" : "\n[red]⚠[lightgray] " + bundle.format("sectorlist.attacked", "[red]" + attacked + "[]")),
@@ -588,6 +588,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
for(Sector sec : all){ for(Sector sec : all){
if(sec.hasBase() && (searchText.isEmpty() || sec.name().toLowerCase().contains(searchText.toLowerCase()))){ if(sec.hasBase() && (searchText.isEmpty() || sec.name().toLowerCase().contains(searchText.toLowerCase()))){
con.button(t -> { con.button(t -> {
t.marginRight(10f);
t.left(); t.left();
t.defaults().growX(); t.defaults().growX();

View File

@@ -301,6 +301,8 @@ public class SettingsMenuDialog extends Dialog{
control.setInput(new DesktopInput()); control.setInput(new DesktopInput());
input.setUseKeyboard(true); input.setUseKeyboard(true);
} }
}else{
Core.settings.put("keyboard", false);
} }
} }
//the issue with touchscreen support on desktop is that: //the issue with touchscreen support on desktop is that:

View File

@@ -303,7 +303,7 @@ public class ConstructBlock extends Block{
int accumulated = (int)(accumulator[i]); //get amount int accumulated = (int)(accumulator[i]); //get amount
if(clampedAmount > 0 && accumulated > 0){ //if it's positive, add it to the core if(clampedAmount > 0 && accumulated > 0){ //if it's positive, add it to the core
if(core != null && requirements[i].item.unlockedNow()){ //only accept items that are unlocked if(core != null && requirements[i].item.unlockedNowHost()){ //only accept items that are unlocked
int accepting = Math.min(accumulated, core.storageCapacity - core.items.get(requirements[i].item)); int accepting = Math.min(accumulated, core.storageCapacity - core.items.get(requirements[i].item));
//transfer items directly, as this is not production. //transfer items directly, as this is not production.
core.items.add(requirements[i].item, accepting); core.items.add(requirements[i].item, accepting);

View File

@@ -109,13 +109,15 @@ public class PowerNode extends PowerBlock{
Core.bundle.format("bar.powerbalance", Core.bundle.format("bar.powerbalance",
((entity.power.graph.getPowerBalance() >= 0 ? "+" : "") + UI.formatAmount((long)(entity.power.graph.getPowerBalance() * 60)))), ((entity.power.graph.getPowerBalance() >= 0 ? "+" : "") + UI.formatAmount((long)(entity.power.graph.getPowerBalance() * 60)))),
() -> Pal.powerBar, () -> Pal.powerBar,
() -> Mathf.clamp(entity.power.graph.getLastPowerProduced() / entity.power.graph.getLastPowerNeeded()))); () -> Mathf.clamp(entity.power.graph.getLastPowerProduced() / entity.power.graph.getLastPowerNeeded())
));
bars.add("batteries", entity -> new Bar(() -> bars.add("batteries", entity -> new Bar(() ->
Core.bundle.format("bar.powerstored", Core.bundle.format("bar.powerstored",
(UI.formatAmount((long)entity.power.graph.getLastPowerStored())), UI.formatAmount((long)entity.power.graph.getLastCapacity())), (UI.formatAmount((long)entity.power.graph.getLastPowerStored())), UI.formatAmount((long)entity.power.graph.getLastCapacity())),
() -> Pal.powerBar, () -> Pal.powerBar,
() -> Mathf.clamp(entity.power.graph.getLastPowerStored() / entity.power.graph.getLastCapacity()))); () -> Mathf.clamp(entity.power.graph.getLastPowerStored() / entity.power.graph.getLastCapacity())
));
bars.add("connections", entity -> new Bar(() -> bars.add("connections", entity -> new Bar(() ->
Core.bundle.format("bar.powerlines", entity.power.links.size, maxNodes), Core.bundle.format("bar.powerlines", entity.power.links.size, maxNodes),

View File

@@ -9,6 +9,7 @@ public class PowerVoid extends PowerBlock{
super(name); super(name);
consumes.power(Float.MAX_VALUE); consumes.power(Float.MAX_VALUE);
envEnabled = Env.any; envEnabled = Env.any;
enableDrawStatus = false;
} }
@Override @Override

View File

@@ -126,7 +126,7 @@ public class Reconstructor extends UnitBlock{
var upgrade = upgrade(pay.unit.type); var upgrade = upgrade(pay.unit.type);
if(upgrade != null){ if(upgrade != null){
if(!upgrade.unlockedNow()){ if(!upgrade.unlockedNowHost()){
//flash "not researched" //flash "not researched"
pay.showOverlay(Icon.tree); pay.showOverlay(Icon.tree);
} }
@@ -137,7 +137,7 @@ public class Reconstructor extends UnitBlock{
} }
} }
return upgrade != null && upgrade.unlockedNow() && !upgrade.isBanned(); return upgrade != null && upgrade.unlockedNowHost() && !upgrade.isBanned();
} }
@Override @Override
@@ -232,7 +232,7 @@ public class Reconstructor extends UnitBlock{
if(payload == null) return null; if(payload == null) return null;
UnitType t = upgrade(payload.unit.type); UnitType t = upgrade(payload.unit.type);
return t != null && t.unlockedNow() ? t : null; return t != null && t.unlockedNowHost() ? t : null;
} }
public boolean constructing(){ public boolean constructing(){
@@ -241,7 +241,7 @@ public class Reconstructor extends UnitBlock{
public boolean hasUpgrade(UnitType type){ public boolean hasUpgrade(UnitType type){
UnitType t = upgrade(type); UnitType t = upgrade(type);
return t != null && t.unlockedNow() && !type.isBanned(); return t != null && t.unlockedNowHost() && !type.isBanned();
} }
public UnitType upgrade(UnitType type){ public UnitType upgrade(UnitType type){

View File

@@ -43,7 +43,6 @@ public class ConsumeItemFilter extends Consume{
@Override @Override
public void update(Building entity){ public void update(Building entity){
} }
@Override @Override

View File

@@ -13,7 +13,7 @@
}, },
{ {
"name": "Omega", "name": "Omega",
"address": ["yeet.mindustry.me:2345", "yeet.mindustry.me:2076", "yeet.mindustry.me:2222","yeet.mindustry.me:6567", "yeet.mindustry.me:2054", "yeet.mindustry.me:3512"] "address": ["yeet.mindustry.me:6567", "yeet.mindustry.me:2345", "n3.mindustry.me:4444","n2.mindustry.me:4040", "n2.mindustry.me:4002", "n2.mindustry.me:4001"]
}, },
{ {
"name": "MeowLand", "name": "MeowLand",