diff --git a/core/src/io/anuke/mindustry/Vars.java b/core/src/io/anuke/mindustry/Vars.java index 9831b5cec4..eeeebd24ac 100644 --- a/core/src/io/anuke/mindustry/Vars.java +++ b/core/src/io/anuke/mindustry/Vars.java @@ -45,6 +45,8 @@ public class Vars{ public static final Team defaultTeam = Team.blue; /**team of the enemy in waves/sectors*/ public static final Team waveTeam = Team.red; + /**how many times longer a boss wave takes*/ + public static final float bossWaveMultiplier = 3f; /**max chat message length*/ public static final int maxTextLength = 150; /**max player name length in bytes*/ diff --git a/core/src/io/anuke/mindustry/content/Blocks.java b/core/src/io/anuke/mindustry/content/Blocks.java index a1cbf058f2..b9c7048e83 100644 --- a/core/src/io/anuke/mindustry/content/Blocks.java +++ b/core/src/io/anuke/mindustry/content/Blocks.java @@ -833,7 +833,7 @@ public class Blocks implements ContentList{ thermalGenerator = new ThermalGenerator("thermal-generator"){{ requirements(Category.power, ItemStack.with(Items.copper, 80, Items.graphite, 70, Items.lead, 100, Items.silicon, 70, Items.metaglass, 80)); - powerProduction = 2f; + powerProduction = 1.8f; generateEffect = Fx.redgeneratespark; size = 2; }}; @@ -843,6 +843,7 @@ public class Blocks implements ContentList{ powerProduction = 6f; itemDuration = 30f; consumes.liquid(Liquids.water, 0.05f); + hasLiquids = true; size = 2; }}; diff --git a/core/src/io/anuke/mindustry/content/Loadouts.java b/core/src/io/anuke/mindustry/content/Loadouts.java new file mode 100644 index 0000000000..02be51ea60 --- /dev/null +++ b/core/src/io/anuke/mindustry/content/Loadouts.java @@ -0,0 +1,10 @@ +package io.anuke.mindustry.content; + +import io.anuke.mindustry.game.ContentList; + +public class Loadouts implements ContentList{ + + @Override + public void load(){ + } +} diff --git a/core/src/io/anuke/mindustry/content/UnitTypes.java b/core/src/io/anuke/mindustry/content/UnitTypes.java index f841cdb343..5a5a3d8e77 100644 --- a/core/src/io/anuke/mindustry/content/UnitTypes.java +++ b/core/src/io/anuke/mindustry/content/UnitTypes.java @@ -132,7 +132,7 @@ public class UnitTypes implements ContentList{ mass = 5f; hitsize = 20f; rotatespeed = 0.06f; - health = 20000; + health = 4000; weapon = new Weapon("chaos"){{ length = 8f; reload = 50f; @@ -155,7 +155,7 @@ public class UnitTypes implements ContentList{ mass = 5f; hitsize = 20f; rotatespeed = 0.06f; - health = 80000; + health = 10000; weapon = new Weapon("eradication"){{ length = 13f; reload = 30f; @@ -236,7 +236,7 @@ public class UnitTypes implements ContentList{ }}; revenant = new UnitType("revenant", Revenant.class, Revenant::new){{ - health = 4000; + health = 3000; mass = 5f; hitsize = 20f; speed = 0.1f; @@ -266,7 +266,7 @@ public class UnitTypes implements ContentList{ }}; lich = new UnitType("lich", Revenant.class, Revenant::new){{ - health = 15000; + health = 9000; mass = 20f; hitsize = 40f; speed = 0.01f; @@ -297,7 +297,7 @@ public class UnitTypes implements ContentList{ }}; reaper = new UnitType("reaper", Revenant.class, Revenant::new){{ - health = 30000; + health = 20000; mass = 30f; hitsize = 56f; speed = 0.01f; diff --git a/core/src/io/anuke/mindustry/core/ContentLoader.java b/core/src/io/anuke/mindustry/core/ContentLoader.java index 73ad500f80..1d71ff81db 100644 --- a/core/src/io/anuke/mindustry/core/ContentLoader.java +++ b/core/src/io/anuke/mindustry/core/ContentLoader.java @@ -49,6 +49,7 @@ public class ContentLoader{ new Mechs(), new UnitTypes(), new Blocks(), + new Loadouts(), new TechTree(), new Zones(), diff --git a/core/src/io/anuke/mindustry/core/GameState.java b/core/src/io/anuke/mindustry/core/GameState.java index e0738bfa4c..9765ae1786 100644 --- a/core/src/io/anuke/mindustry/core/GameState.java +++ b/core/src/io/anuke/mindustry/core/GameState.java @@ -43,7 +43,7 @@ public class GameState{ } public boolean isPaused(){ - return (is(State.paused) && !Net.active()) || gameOver; + return (is(State.paused) && !Net.active()) || (gameOver && !Net.active()); } public boolean is(State astate){ diff --git a/core/src/io/anuke/mindustry/core/Logic.java b/core/src/io/anuke/mindustry/core/Logic.java index f53b02054d..164a92e322 100644 --- a/core/src/io/anuke/mindustry/core/Logic.java +++ b/core/src/io/anuke/mindustry/core/Logic.java @@ -81,7 +81,7 @@ public class Logic implements ApplicationListener{ public void runWave(){ world.spawner.spawnEnemies(); state.wave++; - state.wavetime = state.rules.waveSpacing; + state.wavetime = world.isZone() && world.getZone().isBossWave(state.wave) ? state.rules.waveSpacing * bossWaveMultiplier : state.rules.waveSpacing; Events.fire(new WaveEvent()); } diff --git a/core/src/io/anuke/mindustry/entities/type/Player.java b/core/src/io/anuke/mindustry/entities/type/Player.java index a8c8b1307c..e973c7126c 100644 --- a/core/src/io/anuke/mindustry/entities/type/Player.java +++ b/core/src/io/anuke/mindustry/entities/type/Player.java @@ -364,8 +364,9 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ @Override public void drawUnder(){ - float size = mech.engineSize * (mech.flying ? 1f : boostHeat); + if(dead) return; + float size = mech.engineSize * (mech.flying ? 1f : boostHeat); Draw.color(mech.engineColor); Fill.circle(x + Angles.trnsx(rotation + 180, mech.engineOffset), y + Angles.trnsy(rotation + 180, mech.engineOffset), size + Mathf.absin(Time.time(), 2f, size/4f)); diff --git a/core/src/io/anuke/mindustry/game/Loadout.java b/core/src/io/anuke/mindustry/game/Loadout.java index 82a1d2425a..85e8b14da2 100644 --- a/core/src/io/anuke/mindustry/game/Loadout.java +++ b/core/src/io/anuke/mindustry/game/Loadout.java @@ -1,17 +1,10 @@ package io.anuke.mindustry.game; -import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; -public enum Loadout{ - test(Blocks.coreShard){ - @Override - public void setup(Tile tile){ - - } - }; - +public abstract class Loadout extends Content{ public final Block core; Loadout(Block core){ @@ -19,4 +12,9 @@ public enum Loadout{ } public abstract void setup(Tile tile); + + @Override + public ContentType getContentType(){ + return ContentType.loadout; + } } diff --git a/core/src/io/anuke/mindustry/type/ContentType.java b/core/src/io/anuke/mindustry/type/ContentType.java index 30189125ee..c20ff0f310 100644 --- a/core/src/io/anuke/mindustry/type/ContentType.java +++ b/core/src/io/anuke/mindustry/type/ContentType.java @@ -11,5 +11,6 @@ public enum ContentType { unit, weather, effect, - zone + zone, + loadout } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java index 62cc23e37a..4b79828534 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java @@ -89,7 +89,7 @@ public class MapsDialog extends FloatingDialog{ TextButton button = maps.addButton("", "clear", () -> showMapInfo(map)).width(mapsize).pad(8).get(); button.clearChildren(); button.margin(9); - button.add(map.meta.tags.get("name", map.name)).growX().center().get().setEllipsis(true); + button.add(map.meta.tags.get("name", map.name)).width(mapsize - 18f).center().get().setEllipsis(true); button.row(); button.addImage("white").growX().pad(4).color(Color.GRAY); button.row(); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java index fbf81611ee..2cd2082af5 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java @@ -39,10 +39,15 @@ public class ZoneInfoDialog extends FloatingDialog{ Table iteminfo = new Table(); Runnable rebuildItems = () -> { + int i = 0; iteminfo.clear(); ItemStack[] stacks = zone.unlocked() ? zone.getLaunchCost() : zone.itemRequirements; for(ItemStack stack : stacks){ if(stack.amount == 0) continue; + + if(i++ % 2 == 0){ + iteminfo.row(); + } iteminfo.addImage(stack.item.icon(Item.Icon.medium)).size(8*3).padRight(1); iteminfo.add(stack.amount + "").color(Color.LIGHT_GRAY).padRight(5); } @@ -157,7 +162,7 @@ public class ZoneInfoDialog extends FloatingDialog{ dialog.cont.row(); } dialog.show(); - }).colspan(4).size(100f, bsize).left(); + }).colspan(4).size(100f, bsize).left().disabled(b -> !content.items().contains(item -> data.getItem(item) > 0 && item.type == ItemType.material && !zone.getStartingItems().contains(stack -> stack.item == item))); }; rebuildLoadout[0].run(); @@ -188,7 +193,7 @@ public class ZoneInfoDialog extends FloatingDialog{ hide(); world.playZone(zone); } - }).size(300f, 70f).padTop(5).disabled(b -> zone.locked() ? !canUnlock(zone) : !data.hasItems(zone.getLaunchCost())).get(); + }).margin(13f).padTop(5).disabled(b -> zone.locked() ? !canUnlock(zone) : !data.hasItems(zone.getLaunchCost())).get(); button.row(); button.add(iteminfo); diff --git a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java index d6be91ed7e..467be52441 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java @@ -134,16 +134,21 @@ public class HudFragment extends Fragment{ cont.row(); //fps display - infolabel = cont.table(t -> { - IntFormat fps = new IntFormat("fps"); - IntFormat ping = new IntFormat("ping"); - t.label(() -> fps.get(Core.graphics.getFramesPerSecond())).padRight(10); - t.row(); - if(Net.hasClient()){ - t.label(() -> ping.get(Net.getPing())).visible(Net::client).colspan(2); - } - }).size(-1).visible(() -> Core.settings.getBool("fps")).update(t -> t.setTranslation(0, - (!waves.isVisible() ? wavetable.getHeight() + healthTable.getHeight() : Math.min(wavetable.getTranslation().y + healthTable.getHeight(), wavetable.getHeight() + healthTable.getHeight())))).get(); + infolabel = new Table(); + IntFormat fps = new IntFormat("fps"); + IntFormat ping = new IntFormat("ping"); + infolabel.label(() -> fps.get(Core.graphics.getFramesPerSecond())).padRight(10); + infolabel.row(); + if(Net.hasClient()){ + infolabel.label(() -> ping.get(Net.getPing())).visible(Net::client).colspan(2); + } + infolabel.visible(() -> Core.settings.getBool("fps")).update(() -> + infolabel.setPosition(0, + healthTable.isVisible() ? healthTable.getY() + healthTable.getTranslation().y : wavetable.isVisible() ? wavetable.getY() : 0f, + Align.topLeft)); + + infolabel.pack(); + cont.addChild(infolabel); //make wave box appear below rest of menu if(mobile){ diff --git a/core/src/io/anuke/mindustry/world/BlockStorage.java b/core/src/io/anuke/mindustry/world/BlockStorage.java index b8cb16ae03..6232f22e4a 100644 --- a/core/src/io/anuke/mindustry/world/BlockStorage.java +++ b/core/src/io/anuke/mindustry/world/BlockStorage.java @@ -68,6 +68,7 @@ public abstract class BlockStorage extends UnlockableContent{ /**Remove a stack from this inventory, and return the amount removed.*/ public int removeStack(Tile tile, Item item, int amount){ + amount = Math.min(amount, tile.entity.items.get(item)); tile.entity.noSleep(); tile.entity.items.remove(item, amount); return amount; diff --git a/core/src/io/anuke/mindustry/world/blocks/power/TurbineGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/TurbineGenerator.java index 05f8daad7d..ed485d9492 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/TurbineGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/TurbineGenerator.java @@ -15,6 +15,6 @@ public class TurbineGenerator extends BurnerGenerator{ @Override public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){ - return super.acceptLiquid(tile, source, liquid, amount) || liquid == consumes.liquid() && tile.entity.liquids.get(consumes.liquid()) < liquidCapacity; + return (liquid == consumes.liquid() && tile.entity.liquids.get(consumes.liquid()) < liquidCapacity); } } diff --git a/server/src/io/anuke/mindustry/server/ServerControl.java b/server/src/io/anuke/mindustry/server/ServerControl.java index f4961adac3..3703d60776 100644 --- a/server/src/io/anuke/mindustry/server/ServerControl.java +++ b/server/src/io/anuke/mindustry/server/ServerControl.java @@ -14,11 +14,8 @@ import io.anuke.arc.util.CommandHandler.ResponseType; import io.anuke.arc.util.Timer.Task; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.entities.type.Player; -import io.anuke.mindustry.game.Difficulty; +import io.anuke.mindustry.game.*; import io.anuke.mindustry.game.EventType.GameOverEvent; -import io.anuke.mindustry.game.RulePreset; -import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.game.Version; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.io.SaveIO; import io.anuke.mindustry.maps.Map; @@ -48,7 +45,7 @@ public class ServerControl implements ApplicationListener{ private FileHandle currentLogFile; private boolean inExtraRound; private Task lastTask; - + private RulePreset lastPreset; public ServerControl(String[] args){ Core.settings.defaults( @@ -214,7 +211,7 @@ public class ServerControl implements ApplicationListener{ try{ preset = RulePreset.valueOf(arg[1]); }catch(IllegalArgumentException e){ - err("No gamemode '{0}' found."); + err("No gamemode '{0}' found.", arg[1]); return; } } @@ -643,7 +640,9 @@ public class ServerControl implements ApplicationListener{ players.add(p); p.setDead(true); } + Rules rules = state.rules; logic.reset(); + state.rules = rules; Call.onWorldDataBegin(); run.run(); logic.play(); diff --git a/tests/src/test/java/ApplicationTests.java b/tests/src/test/java/ApplicationTests.java index d00d090621..9c796a4edb 100644 --- a/tests/src/test/java/ApplicationTests.java +++ b/tests/src/test/java/ApplicationTests.java @@ -241,37 +241,32 @@ public class ApplicationTests{ @Test void zoneEmptyWaves(){ for(Zone zone : content.zones()){ - checkNoEmptyWaves(zone, zone.rules.get().spawns, 1, 100); + Array spawns = zone.rules.get().spawns; + for(int i = 1; i <= 100; i++){ + int total = 0; + for(SpawnGroup spawn : spawns){ + total += spawn.getUnitsSpawned(i); + } + + assertNotEquals(0, total, "Zone " + zone + " has no spawned enemies at wave " + i); + } } } @Test void zoneOverflowWaves(){ for(Zone zone : content.zones()){ - checkExtraWaves(zone, zone.rules.get().spawns, 1, 40, 140); - } - } + Array spawns = zone.rules.get().spawns; - void checkNoEmptyWaves(Zone zone, Array spawns, int from, int to){ - for(int i = from; i <= to; i++){ - int total = 0; - for(SpawnGroup spawn : spawns){ - total += spawn.getUnitsSpawned(i); - } + for(int i = 1; i <= 40; i++){ + int total = 0; + for(SpawnGroup spawn : spawns){ + total += spawn.getUnitsSpawned(i); + } - assertNotEquals(0, total, "Zone " + zone + " has no spawned enemies at wave " + i); - } - } - - void checkExtraWaves(Zone zone, Array spawns, int from, int to, int max){ - for(int i = from; i <= to; i++){ - int total = 0; - for(SpawnGroup spawn : spawns){ - total += spawn.getUnitsSpawned(i); - } - - if(total >= max){ - fail("Zone '" + zone + "' has too many spawned enemies at wave " + i + " : " + total); + if(total >= 140){ + fail("Zone '" + zone + "' has too many spawned enemies at wave " + i + " : " + total); + } } } }