diff --git a/core/assets/maps/groundZero.msav b/core/assets/maps/groundZero.msav index 628ab59ece..da07ea1925 100644 Binary files a/core/assets/maps/groundZero.msav and b/core/assets/maps/groundZero.msav differ diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index e1c53bc981..cd2d11b337 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -1864,7 +1864,7 @@ public class Blocks implements ContentList{ }}; dataProcessor = new ResearchBlock("data-processor"){{ - requirements(Category.effect, BuildVisibility.campaignOnly, with(Items.copper, 200, Items.lead, 100)); + //requirements(Category.effect, BuildVisibility.campaignOnly, with(Items.copper, 200, Items.lead, 100)); size = 3; alwaysUnlocked = true; diff --git a/core/src/mindustry/core/Logic.java b/core/src/mindustry/core/Logic.java index 5b2075d430..64e39aa5ab 100644 --- a/core/src/mindustry/core/Logic.java +++ b/core/src/mindustry/core/Logic.java @@ -171,6 +171,15 @@ public class Logic implements ApplicationListener{ Core.settings.manualSave(); } + public void skipWave(){ + if(state.isCampaign()){ + //warp time spent forward because the wave was just skipped. + state.secinfo.internalTimeSpent += state.wavetime; + } + + state.wavetime = 0; + } + public void runWave(){ spawner.spawnEnemies(); state.wave++; diff --git a/core/src/mindustry/core/NetServer.java b/core/src/mindustry/core/NetServer.java index 210e4650da..119c4d7cb3 100644 --- a/core/src/mindustry/core/NetServer.java +++ b/core/src/mindustry/core/NetServer.java @@ -682,7 +682,7 @@ public class NetServer implements ApplicationListener{ if(action == AdminAction.wave){ //no verification is done, so admins can hypothetically spam waves //not a real issue, because server owners may want to do just that - state.wavetime = 0f; + logic.skipWave(); }else if(action == AdminAction.ban){ netServer.admins.banPlayerIP(other.con.address); other.kick(KickReason.banned); diff --git a/core/src/mindustry/core/UI.java b/core/src/mindustry/core/UI.java index 63078827e9..8dfcefdad9 100644 --- a/core/src/mindustry/core/UI.java +++ b/core/src/mindustry/core/UI.java @@ -63,7 +63,7 @@ public class UI implements ApplicationListener, Loadable{ public DatabaseDialog database; public ContentInfoDialog content; public PlanetDialog planet; - public TechTreeDialog tech; + public ResearchDialog research; public SchematicsDialog schematics; public ModsDialog mods; public ColorPicker picker; @@ -175,7 +175,7 @@ public class UI implements ApplicationListener, Loadable{ maps = new MapsDialog(); content = new ContentInfoDialog(); planet = new PlanetDialog(); - tech = new TechTreeDialog(); + research = new ResearchDialog(); mods = new ModsDialog(); schematics = new SchematicsDialog(); diff --git a/core/src/mindustry/game/Team.java b/core/src/mindustry/game/Team.java index ec2e437f61..b82e8e1f12 100644 --- a/core/src/mindustry/game/Team.java +++ b/core/src/mindustry/game/Team.java @@ -9,6 +9,7 @@ import mindustry.game.Rules.*; import mindustry.game.Teams.*; import mindustry.graphics.*; import mindustry.world.blocks.storage.CoreBlock.*; +import mindustry.world.modules.*; import static mindustry.Vars.*; @@ -71,6 +72,12 @@ public class Team implements Comparable{ hasPalette = true; } + /** @return the core items for this team, or an empty item module. + * Never add to the resulting item module, as it is mutable. */ + public @NonNull ItemModule items(){ + return core() == null ? ItemModule.empty : core().items; + } + /** @return the team-specific rules. */ public TeamRule rules(){ return state.rules.teams.get(this); diff --git a/core/src/mindustry/input/DesktopInput.java b/core/src/mindustry/input/DesktopInput.java index edd418da71..7ae6820a15 100644 --- a/core/src/mindustry/input/DesktopInput.java +++ b/core/src/mindustry/input/DesktopInput.java @@ -333,6 +333,19 @@ public class DesktopInput extends InputHandler{ table.button(Icon.paste, Styles.clearPartiali, () -> { ui.schematics.show(); }); + + table.button(Icon.tree, Styles.clearPartiali, () -> { + ui.research.show(); + }).visible(() -> state.isCampaign()); + + table.button(Icon.map, Styles.clearPartiali, () -> { + ui.planet.show(); + }).visible(() -> state.isCampaign()); + + table.button(Icon.up, Styles.clearPartiali, () -> { + ui.planet.show(state.getSector(), player.team().core()); + }).visible(() -> state.isCampaign()) + .disabled(b -> player.team().core() == null || !player.team().core().items.has(player.team().core().block.requirements)); } void pollInput(){ diff --git a/core/src/mindustry/ui/dialogs/PausedDialog.java b/core/src/mindustry/ui/dialogs/PausedDialog.java index ce8b3e9d8d..f37b1b8b4a 100644 --- a/core/src/mindustry/ui/dialogs/PausedDialog.java +++ b/core/src/mindustry/ui/dialogs/PausedDialog.java @@ -52,9 +52,7 @@ public class PausedDialog extends BaseDialog{ // cont.button("$database", Icon.book, ui.database::show); //} //TODO remove - cont.button("launch core", Icon.warning, () -> ui.planet.show(state.getSector(), player.team().core())) - .disabled(b -> player.team().core() == null || !player.team().core().items.has(player.team().core().block.requirements)) - .visible(() -> state.isCampaign()); + cont.button("nothing", Icon.warning, () -> ui.showInfo("no")); cont.button("$settings", Icon.settings, ui.settings::show); if(!state.rules.tutorial){ diff --git a/core/src/mindustry/ui/dialogs/PlanetDialog.java b/core/src/mindustry/ui/dialogs/PlanetDialog.java index ed847a67d3..7e63b4533f 100644 --- a/core/src/mindustry/ui/dialogs/PlanetDialog.java +++ b/core/src/mindustry/ui/dialogs/PlanetDialog.java @@ -122,7 +122,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ //draw all sector stuff for(Sector sec : planet.sectors){ if(selectAlpha > 0.01f){ - if(/*canLaunch(sec) || sec.unlocked()*/true){ + if(canLaunch(sec) || sec.unlocked()){ if(sec.baseCoverage > 0){ planets.fill(sec, Tmp.c1.set(Team.crux.color).a(0.1f * sec.baseCoverage * selectAlpha), -0.002f); } @@ -230,7 +230,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ new Table(t -> { //TODO localize t.top(); - t.label(() -> "Turn " + universe.turn()).style(Styles.outlineLabel).color(Pal.accent); + t.label(() -> mode == launch ? "Select Launch Sector" : "Turn " + universe.turn()).style(Styles.outlineLabel).color(Pal.accent); })).grow(); } @@ -249,7 +249,9 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ if(doBuffer){ buffer.end(); - buffer.blit(Shaders.screenspace); + Draw.color(color); + Draw.rect(Draw.wrap(buffer.getTexture()), width/2f, height/2f, width, -height); + Draw.color(); } } @@ -302,7 +304,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ if(sector.hasBase() && sector.hasWaves()){ stable.add("[scarlet]Under attack!"); stable.row(); - stable.add("[accent]" + Mathf.ceil(sectorDestructionTurns - (sector.getSecondsPassed() * 60) / turnDuration) + " turn(s) until destruction"); + stable.add("[accent]" + Mathf.ceil(sectorDestructionTurns - (sector.getSecondsPassed() * 60) / turnDuration) + " turn(s)\nuntil destruction"); stable.row(); } diff --git a/core/src/mindustry/ui/dialogs/TechTreeDialog.java b/core/src/mindustry/ui/dialogs/ResearchDialog.java similarity index 92% rename from core/src/mindustry/ui/dialogs/TechTreeDialog.java rename to core/src/mindustry/ui/dialogs/ResearchDialog.java index a09a191b88..f9e7e15392 100644 --- a/core/src/mindustry/ui/dialogs/TechTreeDialog.java +++ b/core/src/mindustry/ui/dialogs/ResearchDialog.java @@ -1,7 +1,6 @@ package mindustry.ui.dialogs; import arc.*; -import arc.func.*; import arc.graphics.*; import arc.graphics.g2d.*; import arc.input.*; @@ -12,12 +11,12 @@ import arc.scene.actions.*; import arc.scene.event.*; import arc.scene.style.*; import arc.scene.ui.*; -import arc.scene.ui.layout.Stack; import arc.scene.ui.layout.*; import arc.struct.*; import arc.util.*; import mindustry.content.*; import mindustry.content.TechTree.*; +import mindustry.game.EventType.*; import mindustry.game.Objectives.*; import mindustry.gen.*; import mindustry.graphics.*; @@ -25,25 +24,25 @@ import mindustry.type.*; import mindustry.ui.*; import mindustry.ui.layout.*; import mindustry.ui.layout.TreeLayout.*; +import mindustry.world.modules.*; import java.util.*; import static mindustry.Vars.*; -public class TechTreeDialog extends BaseDialog{ +public class ResearchDialog extends BaseDialog{ private final float nodeSize = Scl.scl(60f); private ObjectSet nodes = new ObjectSet<>(); private TechTreeNode root = new TechTreeNode(TechTree.root, null); private Rect bounds = new Rect(); private View view; - private Cons selector = c -> {}; - public TechTreeDialog(){ + public ResearchDialog(){ super(""); titleTable.remove(); margin(0f).marginBottom(8); - Stack stack = cont.stack(view = new View()/*, items = new ItemsDisplay()*/).grow().get(); + cont.add(view = new View()).grow().get(); shouldPause = true; @@ -105,13 +104,8 @@ public class TechTreeDialog extends BaseDialog{ }); } - public Dialog show(Cons selector){ - this.selector = selector; - return super.show(); - } - - public Dialog show(){ - return show(c -> {}); + ItemModule items(){ + return state.rules.defaultTeam.items(); } void treeLayout(){ @@ -262,13 +256,9 @@ public class TechTreeDialog extends BaseDialog{ } }); } - }else if(locked(node.node)){ - selector.get(node.node); + }else if(items().has(node.node.requirements) && locked(node.node)){ + unlock(node.node); } - //TODO select it - //else if(data.hasItems(node.node.requirements) && locked(node.node)){ - // unlock(node.node); - //} }); button.hovered(() -> { if(!mobile && hoverNode != button && node.visible){ @@ -288,7 +278,7 @@ public class TechTreeDialog extends BaseDialog{ button.update(() -> { float offset = (Core.graphics.getHeight() % 2) / 2f; button.setPosition(node.x + panX + width / 2f, node.y + panY + height / 2f + offset, Align.center); - button.getStyle().up = !locked(node.node) ? Tex.buttonOver : Tex.button; + button.getStyle().up = !locked(node.node) ? Tex.buttonOver : !items().has(node.node.requirements) ? Tex.buttonRed : Tex.button; ((TextureRegionDrawable)button.getStyle().imageUp) .setRegion(node.visible ? node.node.content.icon(Cicon.medium) : Icon.lock.getRegion()); button.getImage().setColor(!locked(node.node) ? Color.white : Color.gray); @@ -323,11 +313,9 @@ public class TechTreeDialog extends BaseDialog{ panY = ry - bounds.y - oy; } - /* void unlock(TechNode node){ - data.unlockContent(node.content); - //TODO this should not happen - //data.removeItems(node.requirements); + node.content.unlock(); + items().remove(node.requirements); showToast(Core.bundle.format("researched", node.content.localizedName)); checkNodes(root); hoverNode = null; @@ -336,7 +324,7 @@ public class TechTreeDialog extends BaseDialog{ Core.scene.act(); Sounds.unlock.play(); Events.fire(new ResearchEvent(node.content)); - }*/ + } void rebuild(){ ImageButton button = hoverNode; @@ -379,7 +367,7 @@ public class TechTreeDialog extends BaseDialog{ list.image(req.item.icon(Cicon.small)).size(8 * 3).padRight(3); list.add(req.item.localizedName).color(Color.lightGray); list.label(() -> " " + (player.team().core() != null ? Math.min(player.team().core().items.get(req.item), req.amount) + " / " : "") + req.amount) - .update(l -> {}/*l.setColor(data.has(req.item, req.amount) ? Color.lightGray : Color.scarlet)*/);//TODO + .update(l -> l.setColor(items().has(req.item, req.amount) ? Color.lightGray : Color.scarlet));//TODO }).fillX().left(); t.row(); } @@ -404,13 +392,11 @@ public class TechTreeDialog extends BaseDialog{ } }).pad(9); - //TODO research select button - /* if(mobile && locked(node)){ b.row(); b.button("$research", Icon.ok, Styles.nodet, () -> unlock(node)) - .disabled(i -> !data.hasItems(node.requirements)).growX().height(44f).colspan(3); - }*/ + .disabled(i -> !items().has(node.requirements)).growX().height(44f).colspan(3); + } }); infoTable.row(); diff --git a/core/src/mindustry/ui/fragments/HudFragment.java b/core/src/mindustry/ui/fragments/HudFragment.java index c4f15f8b0f..1032a7e749 100644 --- a/core/src/mindustry/ui/fragments/HudFragment.java +++ b/core/src/mindustry/ui/fragments/HudFragment.java @@ -114,7 +114,7 @@ public class HudFragment extends Fragment{ ui.chatfrag.toggle(); } }else if(state.isCampaign()){ - ui.tech.show(); + ui.research.show(); }else{ ui.database.show(); } @@ -134,13 +134,6 @@ public class HudFragment extends Fragment{ cont.row(); } - //TODO BUTTONS FOR VIEWING EXPORTS/IMPORTS/RESEARCH/MAP/ETC - /* - cont.table(t -> { - - }); - cont.row();*/ - cont.update(() -> { if(Core.input.keyTap(Binding.toggle_menus) && !ui.chatfrag.shown() && !Core.scene.hasDialog() && !(Core.scene.getKeyboardFocus() instanceof TextField)){ toggleMenus(); @@ -683,9 +676,9 @@ public class HudFragment extends Fragment{ if(net.client() && player.admin){ Call.adminRequest(player, AdminAction.wave); }else if(inLaunchWave()){ - ui.showConfirm("$confirm", "$launch.skip.confirm", () -> !canSkipWave(), () -> state.wavetime = 0f); + ui.showConfirm("$confirm", "$launch.skip.confirm", () -> !canSkipWave(), () -> logic.skipWave()); }else{ - state.wavetime = 0f; + logic.skipWave(); } }).growY().fillX().right().width(40f) .visible(this::canSkipWave); diff --git a/core/src/mindustry/world/blocks/campaign/ResearchBlock.java b/core/src/mindustry/world/blocks/campaign/ResearchBlock.java index 2ca9d7aee5..4a29cb3e03 100644 --- a/core/src/mindustry/world/blocks/campaign/ResearchBlock.java +++ b/core/src/mindustry/world/blocks/campaign/ResearchBlock.java @@ -178,10 +178,11 @@ public class ResearchBlock extends Block{ @Override public boolean configTapped(){ //configure with tech node - ui.tech.show(node -> { - configure(node); - ui.tech.hide(); - }); + ui.showInfo("this does nothing"); + //ui.research.show(node -> { + // configure(node); + // ui.research.hide(); + //}); return false; } diff --git a/core/src/mindustry/world/modules/ItemModule.java b/core/src/mindustry/world/modules/ItemModule.java index 71cffee56a..ead9f73505 100644 --- a/core/src/mindustry/world/modules/ItemModule.java +++ b/core/src/mindustry/world/modules/ItemModule.java @@ -12,6 +12,8 @@ import java.util.*; import static mindustry.Vars.content; public class ItemModule extends BlockModule{ + public static final ItemModule empty = new ItemModule(); + private static final int windowSize = 60 * 4; private static WindowedMean[] cacheFlow; private static float[] cacheSums;