diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 3613fc242b..f07d54b45b 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -404,6 +404,8 @@ launch.confirm = This will launch all resources in your core.\nYou will not be a launch.skip.confirm = If you skip now, you will not be able to launch until later waves. uncover = Uncover configure = Configure Loadout +bannedblocks = Banned Blocks +addall = Add All configure.locked = [lightgray]Unlock configuring loadout: Wave {0}. configure.invalid = Amount must be a number between 0 and {0}. zone.unlocked = [lightgray]{0} unlocked. diff --git a/core/src/io/anuke/mindustry/game/Rules.java b/core/src/io/anuke/mindustry/game/Rules.java index 0d85482976..94cf4225ad 100644 --- a/core/src/io/anuke/mindustry/game/Rules.java +++ b/core/src/io/anuke/mindustry/game/Rules.java @@ -1,11 +1,11 @@ package io.anuke.mindustry.game; -import io.anuke.annotations.Annotations.Serialize; -import io.anuke.arc.collection.Array; -import io.anuke.mindustry.content.Items; -import io.anuke.mindustry.io.JsonIO; -import io.anuke.mindustry.type.ItemStack; -import io.anuke.mindustry.type.Zone; +import io.anuke.annotations.Annotations.*; +import io.anuke.arc.collection.*; +import io.anuke.mindustry.content.*; +import io.anuke.mindustry.io.*; +import io.anuke.mindustry.type.*; +import io.anuke.mindustry.world.*; /** * Defines current rules on how the game should function. @@ -69,6 +69,8 @@ public class Rules{ public boolean tutorial = false; /** Starting items put in cores */ public Array loadout = Array.with(ItemStack.with(Items.copper, 100)); + /** Blocks that cannot be placed. */ + public ObjectSet bannedBlocks = new ObjectSet<>(); /** Copies this ruleset exactly. Not very efficient at all, do not use often. */ public Rules copy(){ diff --git a/core/src/io/anuke/mindustry/type/Zone.java b/core/src/io/anuke/mindustry/type/Zone.java index 42969fa00b..dcdc0cf124 100644 --- a/core/src/io/anuke/mindustry/type/Zone.java +++ b/core/src/io/anuke/mindustry/type/Zone.java @@ -19,13 +19,14 @@ import static io.anuke.mindustry.Vars.*; public class Zone extends UnlockableContent{ public @NonNull Generator generator; - public Block[] blockRequirements = {}; - public ZoneRequirement[] zoneRequirements = {}; + //public Block[] blockRequirements = {}; + public Objective[] requirements = {}; + public Objective configureObjective; //TODO public Item[] resources = {}; + public Consumer rules = rules -> {}; public boolean alwaysUnlocked; public int conditionWave = Integer.MAX_VALUE; - public int configureWave = 15; public int launchPeriod = 10; public Loadout loadout = Loadouts.basicShard; public TextureRegion preview; diff --git a/core/src/io/anuke/mindustry/ui/dialogs/CustomRulesDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/CustomRulesDialog.java index ae1a63ea71..a2b6ab1159 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/CustomRulesDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/CustomRulesDialog.java @@ -1,32 +1,88 @@ package io.anuke.mindustry.ui.dialogs; +import io.anuke.arc.*; import io.anuke.arc.function.*; import io.anuke.arc.graphics.*; +import io.anuke.arc.scene.style.*; +import io.anuke.arc.scene.ui.*; import io.anuke.arc.scene.ui.layout.*; import io.anuke.arc.util.*; import io.anuke.mindustry.*; import io.anuke.mindustry.content.*; import io.anuke.mindustry.game.*; +import io.anuke.mindustry.gen.*; import io.anuke.mindustry.graphics.*; import io.anuke.mindustry.type.*; +import io.anuke.mindustry.ui.*; +import io.anuke.mindustry.world.*; -import static io.anuke.mindustry.Vars.tilesize; +import static io.anuke.mindustry.Vars.*; public class CustomRulesDialog extends FloatingDialog{ private Table main; private Rules rules; private Supplier resetter; private LoadoutDialog loadoutDialog; + private FloatingDialog banDialog; public CustomRulesDialog(){ super("$mode.custom"); loadoutDialog = new LoadoutDialog(); + banDialog = new FloatingDialog("$bannedblocks"); + banDialog.addCloseButton(); + + banDialog.shown(this::rebuildBanned); + banDialog.buttons.addImageTextButton("$addall", Icon.arrow16Small, () -> { + rules.bannedBlocks.addAll(content.blocks()); + rebuildBanned(); + }).size(210f, 64f); + setFillParent(true); shown(this::setup); addCloseButton(); } + private void rebuildBanned(){ + float previousScroll = banDialog.getChildren().isEmpty() ? 0f : ((ScrollPane)banDialog.getChildren().first()).getScrollY(); + banDialog.cont.clear(); + banDialog.cont.pane(t -> { + t.margin(10f); + for(Block block : rules.bannedBlocks){ + t.table(Styles.flatOver, b -> { + b.left().margin(4f); + b.addImage(block.icon(Cicon.medium)); + b.add(block.localizedName).padLeft(3).growX().left().wrap(); + + b.addImageButton(Icon.cancelSmall, () -> { + rules.bannedBlocks.remove(block); + rebuildBanned(); + }).size(70f).pad(-4f).padLeft(0f); + }).size(300f, 70f); + t.row(); + } + }).get().setScrollYForce(previousScroll); + banDialog.cont.row(); + banDialog.cont.addImageTextButton("$add", Icon.addSmall, () -> { + FloatingDialog dialog = new FloatingDialog("$add"); + content.blocks().each(b -> !rules.bannedBlocks.contains(b), b -> { + int cols = mobile && Core.graphics.isPortrait() ? 4 : 8; + int i = 0; + dialog.cont.addImageButton(new TextureRegionDrawable(b.icon(Cicon.medium)), Styles.cleari, () -> { + rules.bannedBlocks.add(b); + rebuildBanned(); + dialog.hide(); + }).size(80f); + + if(++i % cols == 0){ + dialog.cont.row(); + } + }); + dialog.addCloseButton(); + dialog.show(); + }).size(300f, 64f); + } + public void show(Rules rules, Supplier resetter){ this.rules = rules; this.resetter = resetter; @@ -65,16 +121,17 @@ public class CustomRulesDialog extends FloatingDialog{ number("$rules.buildspeedmultiplier", f -> rules.buildSpeedMultiplier = f, () -> rules.buildSpeedMultiplier); main.addButton("$configure", - () -> loadoutDialog.show( - Blocks.coreShard.itemCapacity, - rules.loadout, - () -> { - rules.loadout.clear(); - rules.loadout.add(new ItemStack(Items.copper, 100)); - }, () -> {}, () -> {} + () -> loadoutDialog.show(Blocks.coreShard.itemCapacity, rules.loadout, + () -> { + rules.loadout.clear(); + rules.loadout.add(new ItemStack(Items.copper, 100)); + }, () -> {}, () -> {} )).left().width(300f); main.row(); + main.addButton("$bannedblocks", banDialog::show).left().width(300f); + main.row(); + title("$rules.title.player"); number("$rules.playerdamagemultiplier", f -> rules.playerDamageMultiplier = f, () -> rules.playerDamageMultiplier); number("$rules.playerhealthmultiplier", f -> rules.playerHealthMultiplier = f, () -> rules.playerHealthMultiplier); diff --git a/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java b/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java index 98ce9f2159..d7231f9878 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java @@ -151,6 +151,11 @@ public class PlacementFragment extends Fragment{ Color color = state.rules.infiniteResources || (core != null && (core.items.has(block.requirements, state.rules.buildCostMultiplier) || state.rules.infiniteResources)) ? Color.white : Color.gray; button.forEach(elem -> elem.setColor(color)); button.setChecked(control.input.block == block); + + if(state.rules.bannedBlocks.contains(block)){ + button.getStyle().imageUp = Icon.cancelSmall; + button.forEach(elem -> elem.setColor(Color.gray)); + } }); button.hovered(() -> hovered = block); @@ -301,7 +306,11 @@ public class PlacementFragment extends Fragment{ returnArray.add(block); } } - returnArray.sort((b1, b2) -> -Boolean.compare(unlocked(b1), unlocked(b2))); + returnArray.sort((b1, b2) -> { + int locked = -Boolean.compare(unlocked(b1), unlocked(b2)); + if(locked != 0) return locked; + return -Boolean.compare(state.rules.bannedBlocks.contains(b1), state.rules.bannedBlocks.contains(b2)); + }); return returnArray; } diff --git a/core/src/io/anuke/mindustry/world/Build.java b/core/src/io/anuke/mindustry/world/Build.java index bb08372000..7d1441314f 100644 --- a/core/src/io/anuke/mindustry/world/Build.java +++ b/core/src/io/anuke/mindustry/world/Build.java @@ -73,6 +73,10 @@ public class Build{ return false; } + if(state.rules.bannedBlocks.contains(type) && !(state.rules.waves && team == waveTeam)){ + return false; + } + if((type.solid || type.solidifes) && Units.anyEntities(x * tilesize + type.offset() - type.size*tilesize/2f, y * tilesize + type.offset() - type.size*tilesize/2f, type.size * tilesize, type.size*tilesize)){ return false; }