diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index ae3ed511c7..e4111913e4 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -1237,6 +1237,7 @@ rules.buildcostmultiplier = Build Cost Multiplier rules.buildspeedmultiplier = Build Speed Multiplier rules.deconstructrefundmultiplier = Deconstruct Refund Multiplier rules.waitForWaveToEnd = Waves Wait for Enemies +rules.wavelimit = Map Ends After Wave rules.dropzoneradius = Drop Zone Radius:[lightgray] (tiles) rules.unitammo = Units Require Ammo [red](may be removed) rules.enemyteam = Enemy Team diff --git a/core/src/mindustry/core/Logic.java b/core/src/mindustry/core/Logic.java index 22bc9259d0..bde8089da8 100644 --- a/core/src/mindustry/core/Logic.java +++ b/core/src/mindustry/core/Logic.java @@ -310,6 +310,9 @@ public class Logic implements ApplicationListener{ Events.fire(new GameOverEvent(left == null ? Team.derelict : left.team)); state.gameOver = true; } + }else if(!state.gameOver && state.rules.waves && (state.enemies == 0 && state.rules.winWave > 0 && state.wave >= state.rules.winWave && !spawner.isSpawning())){ + state.gameOver = true; + Events.fire(new GameOverEvent(state.rules.defaultTeam)); } } } diff --git a/core/src/mindustry/game/Rules.java b/core/src/mindustry/game/Rules.java index 08a97351da..f6445db9ec 100644 --- a/core/src/mindustry/game/Rules.java +++ b/core/src/mindustry/game/Rules.java @@ -113,7 +113,7 @@ public class Rules{ public float waveSpacing = 2 * Time.toMinutes; /** Starting wave spacing; if <=0, uses waveSpacing * 2. */ public float initialWaveSpacing = 0f; - /** Wave after which the player 'wins'. Used in sectors. Use a value <= 0 to disable. */ + /** Wave after which the player 'wins'. Use a value <= 0 to disable. */ public int winWave = 0; /** Base unit cap. Can still be increased by blocks. */ public int unitCap = 0; diff --git a/core/src/mindustry/ui/dialogs/CustomRulesDialog.java b/core/src/mindustry/ui/dialogs/CustomRulesDialog.java index 4d308c5cf2..4f35ae48ac 100644 --- a/core/src/mindustry/ui/dialogs/CustomRulesDialog.java +++ b/core/src/mindustry/ui/dialogs/CustomRulesDialog.java @@ -68,7 +68,7 @@ public class CustomRulesDialog extends BaseDialog{ b.image(con.uiIcon).size(iconMed).padRight(3); b.add(con.localizedName).color(Color.lightGray).padLeft(3).growX().left().wrap(); - b.button(Icon.cancel, Styles.clearNonei, () -> { + b.button(Icon.cancel, Styles.emptyi, () -> { set.remove(con); rebuild[0].run(); }).size(70f).pad(-4f).padLeft(0f); @@ -91,7 +91,7 @@ public class CustomRulesDialog extends BaseDialog{ set.add(b); rebuild[0].run(); dialog.hide(); - }).size(60f); + }).size(60f).tooltip(b.localizedName); if(++i[0] % cols == 0){ t.row(); @@ -101,7 +101,7 @@ public class CustomRulesDialog extends BaseDialog{ dialog.addCloseButton(); dialog.show(); - }).size(300f, 64f); + }).size(300f, 64f).disabled(b -> set.size == content.getBy(type).count(pred)); }; bd.shown(rebuild[0]); @@ -139,15 +139,16 @@ public class CustomRulesDialog extends BaseDialog{ title("@rules.title.waves"); check("@rules.waves", b -> rules.waves = b, () -> rules.waves); - check("@rules.wavetimer", b -> rules.waveTimer = b, () -> rules.waveTimer); - check("@rules.wavesending", b -> rules.waveSending = b, () -> rules.waveSending); - check("@rules.waitForWaveToEnd", b -> rules.waitEnemies = b, () -> rules.waitEnemies); - number("@rules.wavespacing", false, f -> rules.waveSpacing = f * 60f, () -> rules.waveSpacing / 60f, () -> rules.waveTimer, 1, Float.MAX_VALUE); + check("@rules.wavesending", b -> rules.waveSending = b, () -> rules.waveSending, () -> rules.waves); + check("@rules.wavetimer", b -> rules.waveTimer = b, () -> rules.waveTimer, () -> rules.waves); + check("@rules.waitForWaveToEnd", b -> rules.waitEnemies = b, () -> rules.waitEnemies, () -> rules.waves && rules.waveTimer); + numberi("@rules.wavelimit", f -> rules.winWave = f, () -> rules.winWave, () -> rules.waves, 0, Integer.MAX_VALUE); + number("@rules.wavespacing", false, f -> rules.waveSpacing = f * 60f, () -> rules.waveSpacing / 60f, () -> rules.waves && rules.waveTimer, 1, Float.MAX_VALUE); //this is experimental, because it's not clear that 0 makes it default. if(experimental){ - number("@rules.initialwavespacing", false, f -> rules.initialWaveSpacing = f * 60f, () -> rules.initialWaveSpacing / 60f, () -> true, 0, Float.MAX_VALUE); + number("@rules.initialwavespacing", false, f -> rules.initialWaveSpacing = f * 60f, () -> rules.initialWaveSpacing / 60f, () -> rules.waves && rules.waveTimer, 0, Float.MAX_VALUE); } - number("@rules.dropzoneradius", false, f -> rules.dropZoneRadius = f * tilesize, () -> rules.dropZoneRadius / tilesize, () -> true); + number("@rules.dropzoneradius", false, f -> rules.dropZoneRadius = f * tilesize, () -> rules.dropZoneRadius / tilesize, () -> rules.waves); title("@rules.title.resourcesbuilding"); check("@rules.infiniteresources", b -> { @@ -281,7 +282,10 @@ public class CustomRulesDialog extends BaseDialog{ main.button("[#" + team.color + "]" + team.localized() + (team.emoji.isEmpty() ? "" : "[] " + team.emoji), Icon.downOpen, Styles.togglet, () -> { shown[0] = !shown[0]; - }).marginLeft(14f).width(260f).height(55f).checked(a -> shown[0]).row(); + }).marginLeft(14f).width(260f).height(55f).update(t -> { + ((Image)t.getChildren().get(1)).setDrawable(shown[0] ? Icon.upOpen : Icon.downOpen); + t.setChecked(shown[0]); + }).row(); main.collapser(t -> { t.left().defaults().fillX().left().pad(5); diff --git a/core/src/mindustry/ui/dialogs/LoadDialog.java b/core/src/mindustry/ui/dialogs/LoadDialog.java index cc0ca264c0..8c4118db4e 100644 --- a/core/src/mindustry/ui/dialogs/LoadDialog.java +++ b/core/src/mindustry/ui/dialogs/LoadDialog.java @@ -24,7 +24,7 @@ import static mindustry.Vars.*; public class LoadDialog extends BaseDialog{ Table slots; String searchString; - Seq filteredModes; + Seq hidden; TextField searchField; ScrollPane pane; @@ -50,7 +50,7 @@ public class LoadDialog extends BaseDialog{ cont.clear(); slots = new Table(); - filteredModes = new Seq<>(); + hidden = new Seq<>(); pane = new ScrollPane(slots); rebuild(); @@ -67,9 +67,9 @@ public class LoadDialog extends BaseDialog{ boolean sandbox = mode == Gamemode.sandbox; if(Core.atlas.isFound(icon.getRegion()) || sandbox){ search.button(sandbox ? Icon.terrain : icon, Styles.emptyTogglei, () -> { - if(!filteredModes.addUnique(mode)) filteredModes.remove(mode); + if(!hidden.addUnique(mode)) hidden.remove(mode); rebuild(); - }).size(60f).padLeft(-8f).checked(b -> !filteredModes.contains(mode)).tooltip("@mode." + mode.name() + ".name"); + }).size(60f).padLeft(-12f).checked(b -> !hidden.contains(mode)).tooltip("@mode." + mode.name() + ".name"); } } @@ -98,7 +98,7 @@ public class LoadDialog extends BaseDialog{ for(SaveSlot slot : array){ if(slot.isHidden() || (searchString != null && !Strings.stripColors(slot.getName()).toLowerCase().contains(searchString)) - || (!filteredModes.isEmpty() && filteredModes.contains(slot.mode()))){ + || (!hidden.isEmpty() && hidden.contains(slot.mode()))){ continue; } diff --git a/core/src/mindustry/ui/dialogs/SchematicsDialog.java b/core/src/mindustry/ui/dialogs/SchematicsDialog.java index 988491b56c..8c945c3018 100644 --- a/core/src/mindustry/ui/dialogs/SchematicsDialog.java +++ b/core/src/mindustry/ui/dialogs/SchematicsDialog.java @@ -725,7 +725,7 @@ public class SchematicsDialog extends BaseDialog{ r.image(s.item.uiIcon).left().size(iconMed); r.label(() -> { Building core = player.core(); - if(core == null || state.rules.infiniteResources || core.items.has(s.item, s.amount)) return "[lightgray]" + s.amount + ""; + if(core == null || state.isMenu() || state.rules.infiniteResources || core.items.has(s.item, s.amount)) return "[lightgray]" + s.amount + ""; return (core.items.has(s.item, s.amount) ? "[lightgray]" : "[scarlet]") + Math.min(core.items.get(s.item), s.amount) + "[lightgray]/" + s.amount; }).padLeft(2).left().padRight(4); diff --git a/core/src/mindustry/ui/fragments/HudFragment.java b/core/src/mindustry/ui/fragments/HudFragment.java index 9652d56ecd..7b8412171e 100644 --- a/core/src/mindustry/ui/fragments/HudFragment.java +++ b/core/src/mindustry/ui/fragments/HudFragment.java @@ -52,7 +52,7 @@ public class HudFragment{ //warn about guardian/boss waves Events.on(WaveEvent.class, e -> { int max = 10; - int winWave = state.isCampaign() && state.rules.winWave > 0 ? state.rules.winWave : Integer.MAX_VALUE; + int winWave = state.rules.winWave > 0 ? state.rules.winWave : Integer.MAX_VALUE; outer: for(int i = state.wave - 1; i <= Math.min(state.wave + max, winWave - 2); i++){ for(SpawnGroup group : state.rules.spawns){ @@ -822,7 +822,7 @@ public class HudFragment{ return builder; } - if(state.rules.winWave > 1 && state.rules.winWave >= state.wave && state.isCampaign()){ + if(state.rules.winWave > 1 && state.rules.winWave >= state.wave){ builder.append(wavefc.get(state.wave, state.rules.winWave)); }else{ builder.append(wavef.get(state.wave));