From c3881b57de37a9a777850561ca5185556d31d68c Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 25 Jul 2020 13:29:50 -0400 Subject: [PATCH] More research tweaks / Balancing --- core/src/mindustry/content/Blocks.java | 8 +-- core/src/mindustry/content/TechTree.java | 15 +++-- .../mindustry/ctype/UnlockableContent.java | 7 +++ core/src/mindustry/type/UnitType.java | 19 ++++++ .../mindustry/ui/dialogs/ResearchDialog.java | 59 +++++++++++-------- core/src/mindustry/world/Block.java | 8 +++ 6 files changed, 83 insertions(+), 33 deletions(-) diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 606448a5a1..44424ee3c6 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -1717,7 +1717,7 @@ public class Blocks implements ContentList{ }}; additiveReconstructor = new Reconstructor("additive-reconstructor"){{ - requirements(Category.units, with(Items.copper, 50, Items.lead, 120, Items.silicon, 230)); + requirements(Category.units, with(Items.copper, 200, Items.lead, 120, Items.silicon, 90)); size = 3; consumes.power(3f); @@ -1736,7 +1736,7 @@ public class Blocks implements ContentList{ }}; multiplicativeReconstructor = new Reconstructor("multiplicative-reconstructor"){{ - requirements(Category.units, with(Items.copper, 50, Items.lead, 120, Items.silicon, 230)); + requirements(Category.units, with(Items.lead, 650, Items.silicon, 350, Items.titanium, 350, Items.thorium, 650)); size = 5; consumes.power(6f); @@ -1755,7 +1755,7 @@ public class Blocks implements ContentList{ }}; exponentialReconstructor = new Reconstructor("exponential-reconstructor"){{ - requirements(Category.units, with(Items.copper, 50, Items.lead, 120, Items.silicon, 230)); + requirements(Category.units, with(Items.lead, 2000, Items.silicon, 750, Items.titanium, 950, Items.thorium, 450, Items.plastanium, 350, Items.phasefabric, 250)); size = 7; consumes.power(12f); @@ -1771,7 +1771,7 @@ public class Blocks implements ContentList{ }}; tetrativeReconstructor = new Reconstructor("tetrative-reconstructor"){{ - requirements(Category.units, with(Items.copper, 50, Items.lead, 120, Items.silicon, 230)); + requirements(Category.units, with(Items.lead, 4000, Items.silicon, 1500, Items.thorium, 500, Items.plastanium, 50, Items.phasefabric, 600, Items.surgealloy, 500)); size = 9; consumes.power(25f); diff --git a/core/src/mindustry/content/TechTree.java b/core/src/mindustry/content/TechTree.java index a05bad0db2..6137edb3c2 100644 --- a/core/src/mindustry/content/TechTree.java +++ b/core/src/mindustry/content/TechTree.java @@ -20,9 +20,7 @@ public class TechTree implements ContentList{ @Override public void load(){ - TechNode.context = null; - map = new ObjectMap<>(); - all = new Seq<>(); + setup(); root = node(coreShard, () -> { @@ -406,6 +404,12 @@ public class TechTree implements ContentList{ }); } + private static void setup(){ + TechNode.context = null; + map = new ObjectMap<>(); + all = new Seq<>(); + } + private static TechNode node(UnlockableContent content, Runnable children){ ItemStack[] requirements; @@ -452,7 +456,7 @@ public class TechTree implements ContentList{ /** Item requirements for this content. */ public ItemStack[] requirements; /** Extra objectives needed to research this. TODO implement */ - public Objective[] objectives = {}; + public Seq objectives = new Seq<>(); /** Time required to research this content, in seconds. */ public float time = 60; /** Nodes that depend on this node. */ @@ -471,7 +475,8 @@ public class TechTree implements ContentList{ this.depth = parent == null ? 0 : parent.depth + 1; this.progress = Core.settings == null ? 0 : Core.settings.getFloat("research-" + content.name, 0f); - objectives = Seq.with(requirements).select(i -> !i.item.alwaysUnlocked).map(i -> new Research(i.item)).toArray(Objective.class); + //add dependencies as objectives. + content.getDependencies(d -> objectives.add(new Research(d))); map.put(content, this); context = this; diff --git a/core/src/mindustry/ctype/UnlockableContent.java b/core/src/mindustry/ctype/UnlockableContent.java index 211854c453..65e168c54a 100644 --- a/core/src/mindustry/ctype/UnlockableContent.java +++ b/core/src/mindustry/ctype/UnlockableContent.java @@ -1,6 +1,7 @@ package mindustry.ctype; import arc.*; +import arc.func.*; import arc.graphics.g2d.*; import arc.scene.ui.layout.*; import arc.util.ArcAnnotate.*; @@ -59,6 +60,12 @@ public abstract class UnlockableContent extends MappableContent{ return cicons[icon.ordinal()]; } + /** Iterates through any implicit dependencies of this content. + * For blocks, this would be the items required to build it. */ + public void getDependencies(Cons cons){ + + } + /** This should show all necessary info about this content in the specified table. */ public abstract void displayInfo(Table table); diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java index 6d211e7860..68f351118f 100644 --- a/core/src/mindustry/type/UnitType.java +++ b/core/src/mindustry/type/UnitType.java @@ -24,8 +24,10 @@ import mindustry.game.*; import mindustry.gen.*; import mindustry.graphics.*; import mindustry.ui.*; +import mindustry.world.*; import mindustry.world.blocks.environment.*; import mindustry.world.blocks.payloads.*; +import mindustry.world.blocks.units.*; import static mindustry.Vars.*; @@ -150,6 +152,23 @@ public class UnitType extends UnlockableContent{ } + @Override + public void getDependencies(Cons cons){ + //units require reconstructors being researched + for(Block block : content.blocks()){ + if(block instanceof Reconstructor){ + Reconstructor r = (Reconstructor)block; + for(UnitType[] recipe : r.upgrades){ + //result of reconstruction is this, so it must be a dependency + if(recipe[1] == this){ + cons.get(block); + } + } + } + } + } + + @Override public void displayInfo(Table table){ ContentDisplay.displayUnit(table, this); diff --git a/core/src/mindustry/ui/dialogs/ResearchDialog.java b/core/src/mindustry/ui/dialogs/ResearchDialog.java index 0defdf1d25..007544f66b 100644 --- a/core/src/mindustry/ui/dialogs/ResearchDialog.java +++ b/core/src/mindustry/ui/dialogs/ResearchDialog.java @@ -170,12 +170,17 @@ public class ResearchDialog extends BaseDialog{ void checkNodes(TechTreeNode node){ boolean locked = locked(node.node); if(!locked) node.visible = true; + node.selectable = selectable(node.node); for(TechTreeNode l : node.children){ l.visible = !locked; checkNodes(l); } } + boolean selectable(TechNode node){ + return !node.objectives.contains(i -> !i.complete()); + } + void showToast(String info){ Table table = new Table(); table.actions(Actions.fadeOut(0.5f, Interp.fade), Actions.remove()); @@ -189,7 +194,7 @@ public class ResearchDialog extends BaseDialog{ } boolean locked(TechNode node){ - return node.content.locked() || Structs.contains(node.requirements, i -> i.item.locked()); + return node.content.locked(); } class LayoutNode extends TreeNode{ @@ -207,7 +212,7 @@ public class ResearchDialog extends BaseDialog{ class TechTreeNode extends TreeNode{ final TechNode node; - boolean visible = true; + boolean visible = true, selectable = true; TechTreeNode(TechNode node, TechTreeNode parent){ this.node = node; @@ -278,10 +283,10 @@ public class ResearchDialog 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 : !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); + button.getStyle().up = !locked(node.node) ? Tex.buttonOver : selectable(node.node) && !items().has(node.node.requirements) ? Tex.buttonRed : Tex.button; + + ((TextureRegionDrawable)button.getStyle().imageUp).setRegion(node.selectable ? node.node.content.icon(Cicon.medium) : Icon.lock.getRegion()); + button.getImage().setColor(!locked(node.node) ? Color.white : node.selectable ? Color.gray : Pal.gray); }); addChild(button); } @@ -314,7 +319,7 @@ public class ResearchDialog extends BaseDialog{ } boolean canUnlock(TechNode node){ - return items().has(node.requirements) && !Structs.contains(node.objectives, o -> !o.complete()); + return items().has(node.requirements) && selectable(node); } void unlock(TechNode node){ @@ -353,36 +358,42 @@ public class ResearchDialog extends BaseDialog{ infoTable.left(); infoTable.background(Tex.button).margin(8f); + boolean selectable = selectable(node); + infoTable.table(b -> { b.margin(0).left().defaults().left(); - b.button(Icon.info, Styles.cleari, () -> ui.content.show(node.content)).growY().width(50f); + if(selectable){ + b.button(Icon.info, Styles.cleari, () -> ui.content.show(node.content)).growY().width(50f); + } b.add().grow(); b.table(desc -> { desc.left().defaults().left(); - desc.add(node.content.localizedName); + desc.add(selectable ? node.content.localizedName : "[accent]???"); desc.row(); if(locked(node)){ + desc.table(t -> { t.left(); - for(ItemStack req : node.requirements){ - t.table(list -> { - list.left(); - 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(items().has(req.item, req.amount) ? Color.lightGray : Color.scarlet));//TODO - }).fillX().left(); - t.row(); - } - - //TODO test if this works - if(node.objectives.length > 0){ + if(selectable){ + for(ItemStack req : node.requirements){ + t.table(list -> { + list.left(); + 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(items().has(req.item, req.amount) ? Color.lightGray : Color.scarlet));//TODO + }).fillX().left(); + t.row(); + } + }else if(node.objectives.size > 0){ t.table(r -> { r.add("$complete").colspan(2).left(); r.row(); for(Objective o : node.objectives){ - r.add(o.display()).color(Color.lightGray).left().padLeft(15f); + if(o.complete()) continue; + + r.add("> " + o.display()).color(Color.lightGray).left(); r.image(o.complete() ? Icon.ok : Icon.cancel, o.complete() ? Color.lightGray : Color.scarlet).padLeft(3); r.row(); } @@ -403,7 +414,7 @@ public class ResearchDialog extends BaseDialog{ }); infoTable.row(); - if(node.content.description != null){ + if(node.content.description != null && selectable){ infoTable.table(t -> t.margin(3f).left().labelWrap(node.content.displayDescription()).color(Color.lightGray).growX()).fillX(); } diff --git a/core/src/mindustry/world/Block.java b/core/src/mindustry/world/Block.java index b524fadda3..23d141924e 100644 --- a/core/src/mindustry/world/Block.java +++ b/core/src/mindustry/world/Block.java @@ -584,6 +584,14 @@ public class Block extends UnlockableContent{ } } + @Override + public void getDependencies(Cons cons){ + //just requires items + for(ItemStack stack : requirements){ + cons.get(stack.item); + } + } + @Override public void displayInfo(Table table){ ContentDisplay.displayBlock(table, this);