diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 3a331596e9..e9cdddaae0 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -217,7 +217,6 @@ text.editor.description = Description\: text.editor.name = Name\: text.editor.teams = Teams text.editor.elevation = Elevation -text.editor.badsize = [orange]Invalid image dimensions\![]\nValid map dimensions\: {0} text.editor.errorimageload = Error loading file\:\n[orange]{0} text.editor.errorimagesave = Error saving file\:\n[orange]{0} text.editor.generate = Generate @@ -348,10 +347,8 @@ setting.difficulty.easy = easy setting.difficulty.normal = normal setting.difficulty.hard = hard setting.difficulty.insane = insane -setting.difficulty.purge = purge setting.difficulty.name = Difficulty\: setting.screenshake.name = Screen Shake -setting.indicators.name = Enemy Indicators setting.effects.name = Display Effects setting.sensitivity.name = Controller Sensitivity setting.saveinterval.name = Autosave Interval @@ -361,7 +358,6 @@ setting.multithread.name = Multithreading setting.fps.name = Show FPS setting.vsync.name = VSync setting.lasers.name = Show Power Lasers -setting.healthbars.name = Show Entity Health bars setting.minimap.name = Show Minimap setting.musicvol.name = Music Volume setting.mutemusic.name = Mute Music diff --git a/core/src/io/anuke/mindustry/content/blocks/ProductionBlocks.java b/core/src/io/anuke/mindustry/content/blocks/ProductionBlocks.java index 740f841e0a..8bd571620b 100644 --- a/core/src/io/anuke/mindustry/content/blocks/ProductionBlocks.java +++ b/core/src/io/anuke/mindustry/content/blocks/ProductionBlocks.java @@ -38,7 +38,7 @@ public class ProductionBlocks extends BlockList implements ContentList{ updateEffect = BlockFx.pulverizeMedium; drillEffect = BlockFx.mineBig; - consumes.power(0.16f); + consumes.power(0.11f); }}; blastDrill = new Drill("blast-drill"){{ @@ -80,7 +80,7 @@ public class ProductionBlocks extends BlockList implements ContentList{ liquidCapacity = 30f; rotateSpeed = 1.4f; - consumes.power(0.1f); + consumes.power(0.09f); }}; oilExtractor = new Fracker("oil-extractor"){{ diff --git a/core/src/io/anuke/mindustry/core/NetServer.java b/core/src/io/anuke/mindustry/core/NetServer.java index 8223661499..f6572cd6d4 100644 --- a/core/src/io/anuke/mindustry/core/NetServer.java +++ b/core/src/io/anuke/mindustry/core/NetServer.java @@ -327,9 +327,9 @@ public class NetServer extends Module{ player.getPlaceQueue().clear(); for(BuildRequest req : requests){ //auto-skip done requests - if(req.remove && world.tile(req.x, req.y).block() == Blocks.air){ + if(req.breaking && world.tile(req.x, req.y).block() == Blocks.air){ continue; - }else if(!req.remove && world.tile(req.x, req.y).block() == req.recipe.result && (!req.recipe.result.rotate || world.tile(req.x, req.y).getRotation() == req.rotation)){ + }else if(!req.breaking && world.tile(req.x, req.y).block() == req.recipe.result && (!req.recipe.result.rotate || world.tile(req.x, req.y).getRotation() == req.rotation)){ continue; } player.getPlaceQueue().addLast(req); diff --git a/core/src/io/anuke/mindustry/entities/Player.java b/core/src/io/anuke/mindustry/entities/Player.java index dd3e18ce1a..c8f595fb08 100644 --- a/core/src/io/anuke/mindustry/entities/Player.java +++ b/core/src/io/anuke/mindustry/entities/Player.java @@ -420,7 +420,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra for(BuildRequest request : getPlaceQueue()){ if(getCurrentRequest() == request) continue; - if(request.remove){ + if(request.breaking){ Block block = world.tile(request.x, request.y).target().block(); //draw removal request diff --git a/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java b/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java index 2b1ff13c11..a086bea466 100644 --- a/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java @@ -8,6 +8,7 @@ import io.anuke.mindustry.content.fx.BlockFx; import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.game.EventType.BuildSelectEvent; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.net.Net; @@ -18,6 +19,7 @@ import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.BuildBlock; import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity; import io.anuke.ucore.core.Effects; +import io.anuke.ucore.core.Events; import io.anuke.ucore.core.Timers; import io.anuke.ucore.entities.trait.Entity; import io.anuke.ucore.graphics.Draw; @@ -65,10 +67,10 @@ public interface BuilderTrait extends Entity{ BuildRequest request = getCurrentRequest(); if(request != null){ - output.writeByte(request.remove ? 1 : 0); + output.writeByte(request.breaking ? 1 : 0); output.writeInt(world.toPacked(request.x, request.y)); output.writeFloat(request.progress); - if(!request.remove){ + if(!request.breaking){ output.writeByte(request.recipe.id); output.writeByte(request.rotation); } @@ -181,18 +183,16 @@ public interface BuilderTrait extends Entity{ setMineTile(null); } - - Tile tile = world.tile(current.x, current.y); if(unit.distanceTo(tile) > placeDistance){ return; } - if(!(tile.block() instanceof BuildBlock) ){ - if(canCreateBlocks() && !current.remove && Build.validPlace(unit.getTeam(), current.x, current.y, current.recipe.result, current.rotation)){ + if(!(tile.block() instanceof BuildBlock)){ + if(canCreateBlocks() && !current.breaking && Build.validPlace(unit.getTeam(), current.x, current.y, current.recipe.result, current.rotation)){ Build.beginPlace(unit.getTeam(), current.x, current.y, current.recipe, current.rotation); - }else if(canCreateBlocks() && current.remove && Build.validBreak(unit.getTeam(), current.x, current.y)){ + }else if(canCreateBlocks() && current.breaking && Build.validBreak(unit.getTeam(), current.x, current.y)){ Build.beginBreak(unit.getTeam(), current.x, current.y); }else{ getPlaceQueue().removeFirst(); @@ -222,7 +222,7 @@ public interface BuilderTrait extends Entity{ //progress is synced, thus not updated clientside if(!Net.client()){ //deconstructing is 2x as fast - if(current.remove){ + if(current.breaking){ entity.deconstruct(unit, core, 2f / entity.buildCost * Timers.delta() * getBuildPower(tile)); }else{ entity.construct(unit, core, 1f / entity.buildCost * Timers.delta() * getBuildPower(tile)); @@ -232,6 +232,11 @@ public interface BuilderTrait extends Entity{ }else{ entity.progress = current.progress; } + + if(!current.initialized){ + Events.fire(new BuildSelectEvent(tile, unit.getTeam(), this, current.breaking)); + current.initialized = true; + } } /**Do not call directly.*/ @@ -352,9 +357,10 @@ public interface BuilderTrait extends Entity{ class BuildRequest{ public final int x, y, rotation; public final Recipe recipe; - public final boolean remove; + public final boolean breaking; public float progress; + public boolean initialized; /**This creates a build request.*/ public BuildRequest(int x, int y, int rotation, Recipe recipe){ @@ -362,7 +368,7 @@ public interface BuilderTrait extends Entity{ this.y = y; this.rotation = rotation; this.recipe = recipe; - this.remove = false; + this.breaking = false; } /**This creates a remove request.*/ @@ -371,7 +377,7 @@ public interface BuilderTrait extends Entity{ this.y = y; this.rotation = -1; this.recipe = Recipe.getByResult(world.tile(x, y).block()); - this.remove = true; + this.breaking = true; } } } diff --git a/core/src/io/anuke/mindustry/entities/units/types/Drone.java b/core/src/io/anuke/mindustry/entities/units/types/Drone.java index 9e2e288873..7e906ef758 100644 --- a/core/src/io/anuke/mindustry/entities/units/types/Drone.java +++ b/core/src/io/anuke/mindustry/entities/units/types/Drone.java @@ -4,6 +4,7 @@ import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.utils.Queue; import io.anuke.mindustry.content.blocks.Blocks; import io.anuke.mindustry.content.fx.BlockFx; +import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.traits.BuilderTrait; @@ -12,7 +13,8 @@ import io.anuke.mindustry.entities.units.BaseUnit; import io.anuke.mindustry.entities.units.FlyingUnit; import io.anuke.mindustry.entities.units.UnitCommand; import io.anuke.mindustry.entities.units.UnitState; -import io.anuke.mindustry.game.EventType.BlockBuildEvent; +import io.anuke.mindustry.game.EventType.BlockBuildBeginEvent; +import io.anuke.mindustry.game.EventType.BuildSelectEvent; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.net.Net; @@ -35,7 +37,8 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; -import static io.anuke.mindustry.Vars.*; +import static io.anuke.mindustry.Vars.unitGroups; +import static io.anuke.mindustry.Vars.world; public class Drone extends FlyingUnit implements BuilderTrait{ protected static float discoverRange = 120f; @@ -44,6 +47,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{ protected Item targetItem; protected Tile mineTile; protected Queue placeQueue = new ThreadQueue<>(); + protected boolean isBreaking; public final UnitState @@ -66,9 +70,13 @@ public class Drone extends FlyingUnit implements BuilderTrait{ if(core == null) return; - if(entity.progress() < 1f && entity.tile.block() instanceof BuildBlock){ //building is valid + if((entity.progress() < 1f || entity.progress() > 0f) && entity.tile.block() instanceof BuildBlock){ //building is valid if(!isBuilding() && distanceTo(target) < placeDistance * 0.9f){ //within distance, begin placing - getPlaceQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y, entity.tile.getRotation(), entity.recipe)); + if(isBreaking){ + getPlaceQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y)); + }else{ + getPlaceQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y, entity.tile.getRotation(), entity.recipe)); + } } //if it's missing requirements, try and mine them @@ -234,27 +242,40 @@ public class Drone extends FlyingUnit implements BuilderTrait{ }; static{ - Events.on(BlockBuildEvent.class, event -> { + + Events.on(BuildSelectEvent.class, event -> { EntityGroup group = unitGroups[event.team.ordinal()]; - if(!(event.tile.entity instanceof BuildEntity)) return; + if(!(event.builder instanceof Player) || !(event.tile.entity instanceof BuildEntity)) return; BuildEntity entity = event.tile.entity(); for(BaseUnit unit : group.all()){ if(unit instanceof Drone){ - ((Drone) unit).notifyPlaced(entity); + Drone drone = (Drone)unit; + synchronized(drone.getPlaceQueue()){ + if(drone.isBuilding()){ + //stop building if opposite building begins. + BuildRequest req = drone.getCurrentRequest(); + if(req.breaking != event.breaking && req.x == event.tile.x && req.y == event.tile.y){ + drone.clearBuilding(); + drone.setState(drone.repair); + } + } + } + + drone.notifyPlaced(entity, event.breaking); } } }); } - private void notifyPlaced(BuildEntity entity){ + private void notifyPlaced(BuildEntity entity, boolean isBreaking){ float timeToBuild = entity.recipe.cost; float dist = Math.min(entity.distanceTo(x, y) - placeDistance, 0); - if(dist / type.maxVelocity < timeToBuild * 0.9f){ - //Call.onDroneBeginBuild(this, entity.tile, entity.recipe); + if(!state.is(build) && dist / type.maxVelocity < timeToBuild * 0.9f){ target = entity; + this.isBreaking = isBreaking; setState(build); } } diff --git a/core/src/io/anuke/mindustry/game/EventType.java b/core/src/io/anuke/mindustry/game/EventType.java index bb66dea689..f2e91965f9 100644 --- a/core/src/io/anuke/mindustry/game/EventType.java +++ b/core/src/io/anuke/mindustry/game/EventType.java @@ -1,6 +1,7 @@ package io.anuke.mindustry.game; import io.anuke.mindustry.core.GameState.State; +import io.anuke.mindustry.entities.traits.BuilderTrait; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.function.Event; @@ -76,14 +77,33 @@ public class EventType{ } } - /**Called when block building begins. The tile's block will nearly always be a BuildBlock.*/ - public static class BlockBuildEvent implements Event{ + /**Called when block building begins by placing down the BuildBlock. + * The tile's block will nearly always be a BuildBlock.*/ + public static class BlockBuildBeginEvent implements Event{ public final Tile tile; public final Team team; + public final boolean breaking; - public BlockBuildEvent(Tile tile, Team team){ + public BlockBuildBeginEvent(Tile tile, Team team, boolean breaking){ this.tile = tile; this.team = team; + this.breaking = breaking; + } + } + + /**Called when a player or drone begins building something. + * This does not necessarily happen when a new BuildBlock is created.*/ + public static class BuildSelectEvent implements Event{ + public final Tile tile; + public final Team team; + public final BuilderTrait builder; + public final boolean breaking; + + public BuildSelectEvent(Tile tile, Team team, BuilderTrait builder, boolean breaking){ + this.tile = tile; + this.team = team; + this.builder = builder; + this.breaking = breaking; } } diff --git a/core/src/io/anuke/mindustry/input/DesktopInput.java b/core/src/io/anuke/mindustry/input/DesktopInput.java index f9c2ac0a39..69fc108654 100644 --- a/core/src/io/anuke/mindustry/input/DesktopInput.java +++ b/core/src/io/anuke/mindustry/input/DesktopInput.java @@ -222,7 +222,7 @@ public class DesktopInput extends InputHandler{ player.isShooting = true; } }else if(Inputs.keyTap(section, "deselect") && (recipe != null || mode != none || player.isBuilding()) && - !(player.getCurrentRequest() != null && player.getCurrentRequest().remove && KeyBinds.get(section, "deselect") == KeyBinds.get(section, "break"))){ + !(player.getCurrentRequest() != null && player.getCurrentRequest().breaking && KeyBinds.get(section, "deselect") == KeyBinds.get(section, "break"))){ if(recipe == null){ player.clearBuilding(); } diff --git a/core/src/io/anuke/mindustry/io/TypeIO.java b/core/src/io/anuke/mindustry/io/TypeIO.java index b55cee8236..294671530f 100644 --- a/core/src/io/anuke/mindustry/io/TypeIO.java +++ b/core/src/io/anuke/mindustry/io/TypeIO.java @@ -165,9 +165,9 @@ public class TypeIO{ public static void writeRequests(ByteBuffer buffer, BuildRequest[] requests){ buffer.putShort((short)requests.length); for(BuildRequest request : requests){ - buffer.put(request.remove ? (byte) 1 : 0); + buffer.put(request.breaking ? (byte) 1 : 0); buffer.putInt(world.toPacked(request.x, request.y)); - if(!request.remove){ + if(!request.breaking){ buffer.put(request.recipe.id); buffer.put((byte) request.rotation); } diff --git a/core/src/io/anuke/mindustry/world/Build.java b/core/src/io/anuke/mindustry/world/Build.java index 6bf1762586..963038a4f4 100644 --- a/core/src/io/anuke/mindustry/world/Build.java +++ b/core/src/io/anuke/mindustry/world/Build.java @@ -5,7 +5,7 @@ import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; import io.anuke.mindustry.content.blocks.Blocks; import io.anuke.mindustry.entities.Units; -import io.anuke.mindustry.game.EventType.BlockBuildEvent; +import io.anuke.mindustry.game.EventType.BlockBuildBeginEvent; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.type.Recipe; @@ -59,6 +59,8 @@ public class Build{ } } + Tile ftile = tile; + threads.runDelay(() -> Events.fire(new BlockBuildBeginEvent(ftile, team, true))); } /**Places a BuildBlock at this location.*/ @@ -100,8 +102,7 @@ public class Build{ } } - - threads.runDelay(() -> Events.fire(new BlockBuildEvent(tile, team))); + threads.runDelay(() -> Events.fire(new BlockBuildBeginEvent(tile, team, false))); } /**Returns whether a tile can be placed at this location by this team.*/ diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/MendProjector.java b/core/src/io/anuke/mindustry/world/blocks/defense/MendProjector.java index b045087bf9..c68cefd5a8 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/MendProjector.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/MendProjector.java @@ -71,27 +71,25 @@ public class MendProjector extends Block{ Effects.effect(BlockFx.healWaveMend, Hue.mix(color, phase, entity.phaseHeat), tile.drawx(), tile.drawy(), realRange); entity.charge = 0f; - Timers.run(10f, () -> { - int tileRange = (int)(realRange / tilesize); - healed.clear(); + int tileRange = (int)(realRange / tilesize); + healed.clear(); - for(int x = -tileRange + tile.x; x <= tileRange + tile.x; x++){ - for(int y = -tileRange + tile.y; y <= tileRange + tile.y; y++){ - if(Vector2.dst(x, y, tile.x, tile.y) > realRange) continue; + for(int x = -tileRange + tile.x; x <= tileRange + tile.x; x++){ + for(int y = -tileRange + tile.y; y <= tileRange + tile.y; y++){ + if(Vector2.dst(x, y, tile.x, tile.y) > realRange) continue; - Tile other = world.tile(x, y); + Tile other = world.tile(x, y); - if(other == null) continue; - other = other.target(); + if(other == null) continue; + other = other.target(); - if(other.getTeamID() == tile.getTeamID() && !healed.contains(other.packedPosition()) && other.entity != null && other.entity.health < other.entity.maxHealth()){ - other.entity.healBy(other.entity.maxHealth() * (healPercent + entity.phaseHeat*phaseBoost)/100f); - Effects.effect(BlockFx.healBlockFull, Hue.mix(color, phase, entity.phaseHeat), other.drawx(), other.drawy(), other.block().size); - healed.add(other.packedPosition()); - } + if(other.getTeamID() == tile.getTeamID() && !healed.contains(other.packedPosition()) && other.entity != null && other.entity.health < other.entity.maxHealth()){ + other.entity.healBy(other.entity.maxHealth() * (healPercent + entity.phaseHeat*phaseBoost)/100f); + Effects.effect(BlockFx.healBlockFull, Hue.mix(color, phase, entity.phaseHeat), other.drawx(), other.drawy(), other.block().size); + healed.add(other.packedPosition()); } } - }); + } } } diff --git a/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java b/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java index 1aa16995f2..b942d7b1a5 100644 --- a/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java +++ b/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java @@ -74,7 +74,9 @@ public class DesktopPlatform extends Platform{ if(!state.is(State.menu)){ presence.state = Strings.capitalize(state.mode.name()); - if(state.mode == GameMode.noWaves){ + if(world.getMap() == null){ + presence.details = "Unknown Map"; + }else if(state.mode.disableWaves){ presence.details = Strings.capitalize(world.getMap().name); }else{ presence.details = Strings.capitalize(world.getMap().name) + " | Wave " + state.wave;