diff --git a/core/assets-raw/sprites/ui/button-map-down.9.png b/core/assets-raw/sprites/ui/button-map-down.9.png index 2b8810da55..00441b4c4c 100644 Binary files a/core/assets-raw/sprites/ui/button-map-down.9.png and b/core/assets-raw/sprites/ui/button-map-down.9.png differ diff --git a/core/assets-raw/sprites/ui/button-map-over.9.png b/core/assets-raw/sprites/ui/button-map-over.9.png index aae6c254f3..d16031fafa 100644 Binary files a/core/assets-raw/sprites/ui/button-map-over.9.png and b/core/assets-raw/sprites/ui/button-map-over.9.png differ diff --git a/core/assets/maps/caves.png b/core/assets/maps/caves.png index 9ddb274fbf..1f8e2f66d8 100644 Binary files a/core/assets/maps/caves.png and b/core/assets/maps/caves.png differ diff --git a/core/assets/maps/sinkhole.png b/core/assets/maps/sinkhole.png index 3c6f893291..ebaffda376 100644 Binary files a/core/assets/maps/sinkhole.png and b/core/assets/maps/sinkhole.png differ diff --git a/core/assets/maps/volcano.png b/core/assets/maps/volcano.png index ec51f382af..97aca5a6ad 100644 Binary files a/core/assets/maps/volcano.png and b/core/assets/maps/volcano.png differ diff --git a/core/assets/ui/uiskin.json b/core/assets/ui/uiskin.json index 7682a3b7fe..62128c4be4 100644 --- a/core/assets/ui/uiskin.json +++ b/core/assets/ui/uiskin.json @@ -14,6 +14,7 @@ com.badlogic.gdx.graphics.Color: { blue: {a: 1, b: 1, g: 0, r: 0 }, grey: {a: 1, b: 0.32, g: 0.32, r: 0.32 }, orange: {hex: "#FFA500"}, + accent: {hex: "f4ba6e"}, vis-blue: {a: 1, b: 0.886, g: 0.631, r: 0.105 }, vis-red: {a: 1, b: 0.047, g: 0, r: 0.862 }, menuitem: {a: 1, b: 0.65, g: 0.65, r: 0.65 }, @@ -51,7 +52,7 @@ io.anuke.ucore.scene.ui.ScrollPane$ScrollPaneStyle: { }, io.anuke.ucore.scene.ui.Window$WindowStyle: { default: {titleFont: default-font, background: window, titleFontColor: orange }, - dialog: {stageBackground: dialogDim, titleFont: default-font, background: window-empty, titleFontColor: orange } + dialog: {stageBackground: dialogDim, titleFont: default-font, background: window-empty, titleFontColor: accent } }, io.anuke.ucore.scene.ui.KeybindDialog$KeybindDialogStyle: { default: {keyColor: red, keyNameColor: white}, diff --git a/core/src/io/anuke/mindustry/Vars.java b/core/src/io/anuke/mindustry/Vars.java index c414d658e3..ad34385288 100644 --- a/core/src/io/anuke/mindustry/Vars.java +++ b/core/src/io/anuke/mindustry/Vars.java @@ -48,7 +48,9 @@ public class Vars{ public static boolean showPaths = true; //number of save slots-- increasing may lead to layout issues //TODO named save slots, possibly with a scroll dialog - public static final int saveSlots = 4; + public static final int saveSlots = 8; + //amount of drops that are left when breaking a block + public static final float breakDropAmount = 0.5f; //only if smoothCamera public static boolean snapCamera = true; diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java index 993a4e48b5..3493342967 100644 --- a/core/src/io/anuke/mindustry/core/Control.java +++ b/core/src/io/anuke/mindustry/core/Control.java @@ -55,6 +55,7 @@ public class Control extends Module{ Tile core; Array spawnpoints = new Array<>(); + boolean shouldUpdateItems = false; float respawntime; @@ -399,7 +400,7 @@ public class Control extends Module{ public void addItem(Item item, int amount){ items.put(item, items.get(item, 0)+amount); - ui.updateItems(); + shouldUpdateItems = true; } public boolean hasItems(ItemStack[] items){ @@ -415,13 +416,13 @@ public class Control extends Module{ public void removeItem(ItemStack req){ items.put(req.item, items.get(req.item, 0)-req.amount); - ui.updateItems(); + shouldUpdateItems = true; } public void removeItems(ItemStack... reqs){ for(ItemStack req : reqs) items.put(req.item, items.get(req.item, 0)-req.amount); - ui.updateItems(); + shouldUpdateItems = true; } public ObjectMap getItems(){ @@ -471,6 +472,11 @@ public class Control extends Module{ } } + if(shouldUpdateItems && Timers.get("updateItems", 8)){ + ui.updateItems(); + shouldUpdateItems = false; + } + if(!GameState.is(State.menu)){ if(Inputs.keyUp("pause") && (GameState.is(State.paused) || GameState.is(State.playing))){ diff --git a/core/src/io/anuke/mindustry/core/UI.java b/core/src/io/anuke/mindustry/core/UI.java index 83531cab22..cf96f2fc41 100644 --- a/core/src/io/anuke/mindustry/core/UI.java +++ b/core/src/io/anuke/mindustry/core/UI.java @@ -97,6 +97,7 @@ public class UI extends SceneModule{ Colors.put("missingitems", Color.SCARLET); Colors.put("health", Color.YELLOW); Colors.put("interact", Color.ORANGE); + Colors.put("accent", Color.valueOf("f4ba6e")); } protected void loadSkin(){ @@ -259,14 +260,14 @@ public class UI extends SceneModule{ loadingtable = new table("loadDim"){{ get().setTouchable(Touchable.enabled); get().addImage("white").growX() - .height(3f).pad(4f).growX().units(Unit.dp).get().setColor(Color.ORANGE); + .height(3f).pad(4f).growX().units(Unit.dp).get().setColor(Colors.get("accent")); row(); - new label("[orange]Loading..."){{ + new label("[accent]Loading..."){{ get().setName("namelabel"); }}.pad(10).units(Unit.dp); row(); get().addImage("white").growX() - .height(3f).pad(4f).growX().units(Unit.dp).get().setColor(Color.ORANGE); + .height(3f).pad(4f).growX().units(Unit.dp).get().setColor(Colors.get("accent")); }}.end().get(); loadingtable.setVisible(false); @@ -323,7 +324,7 @@ public class UI extends SceneModule{ } public void showLoading(){ - showLoading("[orange]Loading.."); + showLoading("[accent]Loading.."); } public void showLoading(String text){ diff --git a/core/src/io/anuke/mindustry/entities/effect/Fx.java b/core/src/io/anuke/mindustry/entities/effect/Fx.java index e6e8cc3d28..448f168fae 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Fx.java +++ b/core/src/io/anuke/mindustry/entities/effect/Fx.java @@ -143,6 +143,16 @@ public class Fx{ }); }), + laserspark = new Effect(14, e -> { + Angles.randLenVectors(e.id, 8, 1f + e.ifract()*11f, (x, y)->{ + float len = 1f+e.fract()*5f; + Draw.color(Color.WHITE, Color.CORAL, e.ifract()); + Draw.alpha(e.ifract()/1.3f); + Draw.lineAngle(e.x + x, e.y + y, Mathf.atan2(x, y), len); + Draw.reset(); + }); + }), + shellsmoke = new Effect(20, e -> { Angles.randLenVectors(e.id, 8, 3f + e.ifract()*17f, (x, y)->{ float size = 2f+e.fract()*5f; diff --git a/core/src/io/anuke/mindustry/ui/FloatingDialog.java b/core/src/io/anuke/mindustry/ui/FloatingDialog.java index 559cfa63fe..66268d6b82 100644 --- a/core/src/io/anuke/mindustry/ui/FloatingDialog.java +++ b/core/src/io/anuke/mindustry/ui/FloatingDialog.java @@ -1,7 +1,7 @@ package io.anuke.mindustry.ui; import com.badlogic.gdx.Input.Keys; -import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.Colors; import com.badlogic.gdx.utils.Align; import io.anuke.ucore.scene.ui.Dialog; @@ -14,7 +14,7 @@ public class FloatingDialog extends Dialog{ setFillParent(true); title().setAlignment(Align.center); getTitleTable().row(); - getTitleTable().addImage("white", Color.ORANGE) + getTitleTable().addImage("white", Colors.get("accent")) .growX().height(3f).pad(4f).units(Unit.dp); } diff --git a/core/src/io/anuke/mindustry/ui/LevelDialog.java b/core/src/io/anuke/mindustry/ui/LevelDialog.java index d29c01897c..180bc2469b 100644 --- a/core/src/io/anuke/mindustry/ui/LevelDialog.java +++ b/core/src/io/anuke/mindustry/ui/LevelDialog.java @@ -59,9 +59,9 @@ public class LevelDialog extends FloatingDialog{ } Table inset = new Table("pane-button"); - inset.add("[orange]"+map.name()).pad(3f).units(Unit.dp); + inset.add("[accent]"+map.name()).pad(3f).units(Unit.dp); inset.row(); - inset.add((StringSupplier)(()->"High Score: [orange]" + Settings.getInt("hiscore" + map.name()))) + inset.add((StringSupplier)(()->"High Score: [accent]" + Settings.getInt("hiscore" + map.name()))) .pad(3f).units(Unit.dp); inset.pack(); diff --git a/core/src/io/anuke/mindustry/ui/LoadDialog.java b/core/src/io/anuke/mindustry/ui/LoadDialog.java index 6f90cfc2f2..f1d8d69bfb 100644 --- a/core/src/io/anuke/mindustry/ui/LoadDialog.java +++ b/core/src/io/anuke/mindustry/ui/LoadDialog.java @@ -8,13 +8,18 @@ import io.anuke.mindustry.Vars; import io.anuke.mindustry.core.GameState; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.io.SaveIO; +import io.anuke.ucore.core.Core; +import io.anuke.ucore.core.Timers; import io.anuke.ucore.scene.ui.Label; +import io.anuke.ucore.scene.ui.ScrollPane; import io.anuke.ucore.scene.ui.TextButton; +import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.scene.ui.layout.Unit; //TODO unified save/load dialogs public class LoadDialog extends FloatingDialog{ - + ScrollPane pane; + public LoadDialog(){ this("Load Game"); } @@ -26,6 +31,7 @@ public class LoadDialog extends FloatingDialog{ shown(() -> { setup(); + Timers.runTask(2f, ()-> Core.scene.setScrollFocus(pane)); }); addCloseButton(); @@ -36,12 +42,18 @@ public class LoadDialog extends FloatingDialog{ content().add("Select a save slot.").padBottom(2); content().row(); + + Table slots = new Table(); + pane = new ScrollPane(slots); + pane.setFadeScrollBars(false); + + slots.padRight(Unit.dp.inPixels(24)); for(int i = 0; i < Vars.saveSlots; i++){ final int slot = i; TextButton button = new TextButton("[orange]Slot " + (i + 1)); - button.pad(Unit.dp.inPixels(10)); + button.pad(Unit.dp.inPixels(12)); button.getLabelCell().top().left().growX(); button.row(); @@ -51,16 +63,18 @@ public class LoadDialog extends FloatingDialog{ ", Wave " + SaveIO.getWave(slot) + "\nLast Saved: " + SaveIO.getTimeString(i))); info.setAlignment(Align.center, Align.center); - button.add(info).padBottom(2).padTop(6); + button.add(info).padBottom(3).padTop(7); button.row(); //button.addImage("white", Color.GRAY) //.growX().height(3f).pad(4f).units(Unit.dp); button.row(); modifyButton(button, slot); - content().add(button).size(400, 86).units(Unit.dp).pad(2); - content().row(); + slots.add(button).size(404, 104).pad(4).units(Unit.dp); + slots.row(); } + + content().add(pane); } diff --git a/core/src/io/anuke/mindustry/ui/MindustryKeybindDialog.java b/core/src/io/anuke/mindustry/ui/MindustryKeybindDialog.java index 03aa115db4..928dd32644 100644 --- a/core/src/io/anuke/mindustry/ui/MindustryKeybindDialog.java +++ b/core/src/io/anuke/mindustry/ui/MindustryKeybindDialog.java @@ -1,7 +1,7 @@ package io.anuke.mindustry.ui; import com.badlogic.gdx.Input.Keys; -import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.Colors; import com.badlogic.gdx.utils.Align; import io.anuke.ucore.scene.ui.Image; @@ -17,7 +17,7 @@ public class MindustryKeybindDialog extends KeybindDialog{ title().setAlignment(Align.center); getTitleTable().row(); getTitleTable().add(new Image("white")) - .growX().height(3f).pad(4f).units(Unit.dp).get().setColor(Color.ORANGE); + .growX().height(3f).pad(4f).units(Unit.dp).get().setColor(Colors.get("accent")); } @Override diff --git a/core/src/io/anuke/mindustry/ui/MindustrySettingsDialog.java b/core/src/io/anuke/mindustry/ui/MindustrySettingsDialog.java index f44cb95fb9..a22b4426d5 100644 --- a/core/src/io/anuke/mindustry/ui/MindustrySettingsDialog.java +++ b/core/src/io/anuke/mindustry/ui/MindustrySettingsDialog.java @@ -1,7 +1,7 @@ package io.anuke.mindustry.ui; import com.badlogic.gdx.Input.Keys; -import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.Colors; import com.badlogic.gdx.utils.Align; import io.anuke.ucore.scene.ui.Image; @@ -15,7 +15,7 @@ public class MindustrySettingsDialog extends SettingsDialog{ title().setAlignment(Align.center); getTitleTable().row(); getTitleTable().add(new Image("white")) - .growX().height(3f).pad(4f).units(Unit.dp).get().setColor(Color.ORANGE); + .growX().height(3f).pad(4f).units(Unit.dp).get().setColor(Colors.get("accent")); } @Override diff --git a/core/src/io/anuke/mindustry/world/Generator.java b/core/src/io/anuke/mindustry/world/Generator.java index 626be9cfc4..a1b29667be 100644 --- a/core/src/io/anuke/mindustry/world/Generator.java +++ b/core/src/io/anuke/mindustry/world/Generator.java @@ -77,7 +77,7 @@ public class Generator{ } if(floor == Blocks.stone || floor == Blocks.grass || floor == Blocks.blackstone || - floor == Blocks.snow){ + floor == Blocks.snow || floor == Blocks.sand){ if(Noise.nnoise(x, y, 8, 1) > 0.2){ floor = Blocks.iron; } @@ -107,7 +107,7 @@ public class Generator{ floor = Blocks.sand; } - if(floor == Blocks.grass && Mathf.chance(0.02) && block == Blocks.air){ + if(floor == Blocks.grass && Mathf.chance(0.03) && block == Blocks.air){ block = Blocks.shrub; } diff --git a/core/src/io/anuke/mindustry/world/Tile.java b/core/src/io/anuke/mindustry/world/Tile.java index 4f28bcaf75..a50e69984e 100644 --- a/core/src/io/anuke/mindustry/world/Tile.java +++ b/core/src/io/anuke/mindustry/world/Tile.java @@ -53,6 +53,7 @@ public class Tile{ return Bits.getLeftByte(blocks); } + /**Return relative rotation to a coordinate. Returns -1 if the coordinate is not near this tile.*/ public int relativeTo(int cx, int cy){ if(x == cx && y == cy - 1) return 1; if(x == cx && y == cy + 1) return 3; diff --git a/core/src/io/anuke/mindustry/world/World.java b/core/src/io/anuke/mindustry/world/World.java index e2891fd724..a5481b99b1 100644 --- a/core/src/io/anuke/mindustry/world/World.java +++ b/core/src/io/anuke/mindustry/world/World.java @@ -12,6 +12,8 @@ import io.anuke.mindustry.Vars; import io.anuke.mindustry.ai.Pathfind; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.effect.Fx; +import io.anuke.mindustry.resource.ItemStack; +import io.anuke.mindustry.resource.Recipe; import io.anuke.mindustry.world.blocks.*; import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Sounds; @@ -320,6 +322,22 @@ public class World extends Module{ if(tile == null) return; + Block block = tile.block(); + Recipe result = null; + + for(Recipe recipe : Recipe.values()){ + if(recipe.result == block){ + result = recipe; + break; + } + } + + if(result != null){ + for(ItemStack stack : result.requirements){ + Vars.control.addItem(stack.item, (int)(stack.amount * Vars.breakDropAmount)); + } + } + if(tile.block().drops != null){ Vars.control.addItem(tile.block().drops.item, tile.block().drops.amount); } diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/PowerBooster.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/PowerBooster.java index 5f596b0edd..d06b209818 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/PowerBooster.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/PowerBooster.java @@ -1,9 +1,14 @@ package io.anuke.mindustry.world.blocks.types.distribution; +import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; +import io.anuke.mindustry.Vars; import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.blocks.types.PowerAcceptor; import io.anuke.mindustry.world.blocks.types.production.Generator; +import io.anuke.ucore.core.Timers; +import io.anuke.ucore.util.Mathf; public class PowerBooster extends Generator{ @@ -11,6 +16,7 @@ public class PowerBooster extends Generator{ super(name); drawRadius = true; explosive = false; + hasLasers = false; } @Override @@ -33,4 +39,49 @@ public class PowerBooster extends Generator{ return entity.power + 0.001f <= powerCapacity; } + + //TODO better distribution + protected void distributePower(Tile tile){ + if(!Timers.get(tile, "generate", powerTime)){ + return; + } + + PowerEntity p = tile.entity(); + + int acceptors = 0; + float flow = 0f; + + //TODO have two phases, where it checks nearby blocks first, then distributes it evenly + for(int i = 0; i < 2; i++){ + for(int x = -powerRange; x <= powerRange; x++){ + for(int y = -powerRange; y <= powerRange; y++){ + + if(x == 0 && y == 0){ + continue; + } + + if(Vector2.dst(x, y, 0, 0) < powerRange){ + Tile dest = Vars.world.tile(tile.x + x, tile.y + y); + if(dest != null && dest.block() instanceof PowerAcceptor && ((PowerAcceptor) dest.block()).acceptsPower(dest)){ + if(i == 1){ + PowerAcceptor block = (PowerAcceptor) dest.block(); + + float transmission = Math.min(flow, p.power); + + float amount = block.addPower(dest, transmission); + p.power -= amount; + }else{ + acceptors++; + } + } + } + } + } + + //TODO better distribution scheme + if(i == 0 && acceptors > 0){ + flow = Mathf.clamp(p.power / acceptors, 0f, powerSpeed / acceptors); + } + } + } } diff --git a/core/src/io/anuke/mindustry/world/blocks/types/production/Generator.java b/core/src/io/anuke/mindustry/world/blocks/types/production/Generator.java index fecfec5056..3f8a040353 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/production/Generator.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/production/Generator.java @@ -25,6 +25,7 @@ public class Generator extends PowerBlock{ public float powerSpeed = 0.06f; public boolean explosive = true; public boolean drawRadius = false; + public boolean hasLasers = true; public Generator(String name) { super(name); @@ -80,7 +81,7 @@ public class Generator extends PowerBlock{ if(entity.power > powerSpeed){ Draw.alpha(1f); }else{ - Draw.alpha(0.75f); + Draw.alpha(0.5f); } for(int i = 0; i < laserDirections; i++){ @@ -97,9 +98,10 @@ public class Generator extends PowerBlock{ PowerEntity entity = tile.entity(); for(int i = 0; i < laserDirections; i++){ - Tile target = laserTarget(tile, (tile.getRotation() + i) - laserDirections/2); + int rot = (tile.getRotation() + i) - laserDirections/2; + Tile target = laserTarget(tile, rot); - if(target == null) continue; + if(target == null || isInterfering(target, rot)) continue; PowerAcceptor p = (PowerAcceptor) target.block(); if(p.acceptsPower(target) && entity.power >= powerSpeed){ @@ -108,7 +110,6 @@ public class Generator extends PowerBlock{ } } - } protected void drawLaserTo(Tile tile, int rotation){ @@ -116,19 +117,42 @@ public class Generator extends PowerBlock{ Tile target = laserTarget(tile, rotation); if(target != null){ - Tmp.v1.set(Angles.translation(rotation * 90, target.block().width * Vars.tilesize/2 + 2f)); + boolean interfering = isInterfering(target, rotation); + + Tmp.v1.set(Angles.translation(rotation * 90, target.block().width * Vars.tilesize/2 + 2f + + (interfering ? + Vector2.dst(tile.worldx(), tile.worldy(), target.worldx(), target.worldy()) / 2f - Vars.tilesize/2f - 1 : 0))); + Angles.translation(rotation * 90, width * Vars.tilesize/2 + 2f); - Draw.tint(Hue.mix(Color.GRAY, Color.WHITE, 0.902f + Mathf.sin(Timers.time(), 1.7f, 0.08f))); + if(!interfering){ + Draw.tint(Hue.mix(Color.GRAY, Color.WHITE, 0.904f + Mathf.sin(Timers.time(), 1.7f, 0.06f))); + }else{ + Draw.tint(Hue.mix(Color.SCARLET, Color.WHITE, 0.902f + Mathf.sin(Timers.time(), 1.7f, 0.08f))); + if(Mathf.chance(Timers.delta() * 0.033)){ + Effects.effect(Fx.laserspark, target.worldx() - Tmp.v1.x, target.worldy() - Tmp.v1.y); + } + } + + float r = interfering ? 0.8f : 0f; - float r = 0f; - - Draw.laser("laser", "laserend", tile.worldx() + Angles.x() + Mathf.range(r), tile.worldy() + Angles.y() + Mathf.range(r), + Draw.laser("laser", "laserend", tile.worldx() + Angles.x(), tile.worldy() + Angles.y(), target.worldx() - Tmp.v1.x + Mathf.range(r), target.worldy() - Tmp.v1.y + Mathf.range(r), 0.7f + Mathf.sin(Timers.time(), 2f, 0.1f * 0)); Draw.color(); } } + + protected boolean isInterfering(Tile target, int rotation){ + if(target.block() instanceof Generator){ + Generator other = (Generator)target.block(); + int relrot = (rotation + 2) % 4; + if(other.hasLasers && Math.abs(target.getRotation() - relrot) <= other.laserDirections/2){ + return true; + } + } + return false; + } protected Tile laserTarget(Tile tile, int rotation){ if(rotation < 0) @@ -150,50 +174,5 @@ public class Generator extends PowerBlock{ } return null; } - - //TODO better distribution - protected void distributePower(Tile tile){ - if(!Timers.get(tile, "generate", powerTime)){ - return; - } - - PowerEntity p = tile.entity(); - - int acceptors = 0; - float flow = 0f; - - //TODO have two phases, where it checks nearby blocks first, then distributes it evenly - for(int i = 0; i < 2; i++){ - for(int x = -powerRange; x <= powerRange; x++){ - for(int y = -powerRange; y <= powerRange; y++){ - - if(x == 0 && y == 0){ - continue; - } - - if(Vector2.dst(x, y, 0, 0) < powerRange){ - Tile dest = Vars.world.tile(tile.x + x, tile.y + y); - if(dest != null && dest.block() instanceof PowerAcceptor && ((PowerAcceptor) dest.block()).acceptsPower(dest)){ - if(i == 1){ - PowerAcceptor block = (PowerAcceptor) dest.block(); - - float transmission = Math.min(flow, p.power); - - float amount = block.addPower(dest, transmission); - p.power -= amount; - }else{ - acceptors++; - } - } - } - } - } - - //TODO better distribution scheme - if(i == 0 && acceptors > 0){ - flow = Mathf.clamp(p.power / acceptors, 0f, powerSpeed / acceptors); - } - } - } }