Tech tree filled out

This commit is contained in:
Anuken
2019-01-19 14:58:29 -05:00
parent 5e951f27c9
commit 4fb0c246db
14 changed files with 1406 additions and 1138 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 139 B

After

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 155 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 B

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 969 KiB

After

Width:  |  Height:  |  Size: 966 KiB

View File

@ -61,7 +61,7 @@ public class Blocks implements ContentList{
core, vault, container, unloader, launchPad, core, vault, container, unloader, launchPad,
//turrets //turrets
duo, scorch, hail, wave, lancer, arc, swarmer, salvo, fuse, ripple, cyclone, spectre, meltdown, duo, hail, arc, wave, lancer, swarmer, salvo, fuse, ripple, cyclone, spectre, meltdown,
//units //units
spiritFactory, phantomFactory, wraithFactory, ghoulFactory, revenantFactory, daggerFactory, titanFactory, spiritFactory, phantomFactory, wraithFactory, ghoulFactory, revenantFactory, daggerFactory, titanFactory,
@ -787,15 +787,6 @@ public class Blocks implements ContentList{
health = 120; health = 120;
}}; }};
scorch = new LiquidTurret("scorch"){{
ammo(Liquids.oil, Bullets.basicFlame);
recoil = 0f;
reload = 4f;
shootCone = 50f;
ammoUseEffect = Fx.shellEjectSmall;
health = 160;
}};
wave = new LiquidTurret("wave"){{ wave = new LiquidTurret("wave"){{
ammo( ammo(
Liquids.water, Bullets.waterShot, Liquids.water, Bullets.waterShot,

View File

@ -1,7 +1,9 @@
package io.anuke.mindustry.content; package io.anuke.mindustry.content;
import io.anuke.arc.collection.Array;
import io.anuke.mindustry.game.ContentList; import io.anuke.mindustry.game.ContentList;
import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.ItemStack;
import io.anuke.mindustry.type.Recipe;
import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block;
import static io.anuke.mindustry.type.ItemStack.with; import static io.anuke.mindustry.type.ItemStack.with;
@ -11,43 +13,273 @@ public class TechTree implements ContentList{
@Override @Override
public void load(){ public void load(){
root = new TechNode(null, with(), root = node(null, with(), () -> {
new TechNode(Blocks.copperWall, with(Items.copper, 100),
new TechNode(Blocks.copperWallLarge, with(Items.copper, 100))
),
new TechNode(Blocks.conveyor, with(Items.copper, 10), node(Blocks.conveyor, with(Items.copper, 100), () -> {
new TechNode(Blocks.router, with(Items.copper, 10), node(Blocks.launchPad, with(Items.copper, 100), () -> {
new TechNode(Blocks.distributor, with(Items.copper, 10)),
new TechNode(Blocks.overflowGate, with(Items.copper, 10)),
new TechNode(Blocks.sorter, with(Items.copper, 10))
),
new TechNode(Blocks.junction, with(Items.copper, 10)),
new TechNode(Blocks.itemBridge, with(Items.copper, 10))
),
new TechNode(Blocks.conduit, with(Items.metaglass, 10), });
new TechNode(Blocks.liquidJunction, with(Items.metaglass, 10)),
new TechNode(Blocks.liquidRouter, with(Items.metaglass, 10), node(Blocks.junction, with(Items.copper, 100), () -> {
new TechNode(Blocks.liquidTank, with(Items.metaglass, 10)) node(Blocks.itemBridge, with(Items.copper, 100));
) node(Blocks.router, with(Items.copper, 100), () -> {
) node(Blocks.distributor, with(Items.copper, 100));
); node(Blocks.overflowGate, with(Items.copper, 100));
node(Blocks.sorter, with(Items.copper, 100));
node(Blocks.container, with(Items.copper, 100), () -> {
node(Blocks.unloader, with(Items.copper, 100));
node(Blocks.vault, with(Items.copper, 100), () -> {
});
});
});
node(Blocks.titaniumConveyor, with(Items.copper, 100), () -> {
node(Blocks.phaseConveyor, with(Items.copper, 100), () -> {
node(Blocks.massDriver, with(Items.copper, 100), () -> {
});
});
});
});
});
node(Blocks.duo, with(Items.copper, 100), () -> {
node(Blocks.hail, with(Items.copper, 100), () -> {
node(Blocks.salvo, with(Items.copper, 100), () -> {
node(Blocks.swarmer, with(Items.copper, 100), () -> {
node(Blocks.cyclone, with(Items.copper, 100), () -> {
node(Blocks.spectre, with(Items.copper, 100), () -> {
});
});
});
node(Blocks.ripple, with(Items.copper, 100), () -> {
node(Blocks.fuse, with(Items.copper, 100), () -> {
});
});
});
});
node(Blocks.arc, with(Items.copper, 100), () -> {
node(Blocks.wave, with(Items.copper, 100), () -> {
});
node(Blocks.lancer, with(Items.copper, 100), () -> {
node(Blocks.meltdown, with(Items.copper, 100), () -> {
});
node(Blocks.shockMine, with(Items.metaglass, 100), () -> {
});
});
});
node(Blocks.copperWall, with(Items.copper, 100), () -> {
node(Blocks.copperWallLarge, with(Items.copper, 100));
node(Blocks.titaniumWall, with(Items.copper, 100), () -> {
node(Blocks.door, with(Items.copper, 100), () -> {
node(Blocks.doorLarge, with(Items.copper, 100));
});
node(Blocks.titaniumWallLarge, with(Items.copper, 100));
node(Blocks.thoriumWall, with(Items.copper, 100), () -> {
node(Blocks.thoriumWallLarge, with(Items.copper, 100));
node(Blocks.surgeWall, with(Items.copper, 100), () -> {
node(Blocks.surgeWallLarge, with(Items.copper, 100));
node(Blocks.phaseWall, with(Items.copper, 100), () -> {
node(Blocks.phaseWallLarge, with(Items.copper, 100));
});
});
});
});
});
});
node(Blocks.mechanicalDrill, with(Items.copper, 100), () -> {
node(Blocks.pneumaticDrill, with(Items.copper, 100), () -> {
node(Blocks.cultivator, with(Items.copper, 100), () -> {
});
node(Blocks.laserDrill, with(Items.copper, 100), () -> {
node(Blocks.blastDrill, with(Items.copper, 100), () -> {
});
node(Blocks.waterExtractor, with(Items.copper, 100), () -> {
node(Blocks.oilExtractor, with(Items.copper, 100), () -> {
});
});
});
});
node(Blocks.siliconSmelter, with(Items.copper, 100), () -> {
node(Blocks.pyratiteMixer, with(Items.copper, 100), () -> {
node(Blocks.blastMixer, with(Items.copper, 100), () -> {
});
});
node(Blocks.biomatterCompressor, with(Items.copper, 100), () -> {
node(Blocks.plastaniumCompressor, with(Items.copper, 100), () -> {
node(Blocks.phaseWeaver, with(Items.copper, 100), () -> {
});
});
});
node(Blocks.incinerator, with(Items.copper, 100), () -> {
node(Blocks.melter, with(Items.copper, 100), () -> {
node(Blocks.surgeSmelter, with(Items.copper, 100), () -> {
});
node(Blocks.separator, with(Items.copper, 100), () -> {
node(Blocks.pulverizer, with(Items.copper, 100), () -> {
});
});
node(Blocks.cryofluidMixer, with(Items.copper, 100), () -> {
});
});
});
});
node(Blocks.mechanicalPump, with(Items.metaglass, 100), () -> {
node(Blocks.conduit, with(Items.metaglass, 100), () -> {
node(Blocks.liquidJunction, with(Items.metaglass, 100), () -> {
node(Blocks.liquidRouter, with(Items.metaglass, 100), () -> {
node(Blocks.liquidTank, with(Items.metaglass, 100));
node(Blocks.pulseConduit, with(Items.metaglass, 100), () -> {
node(Blocks.phaseConduit, with(Items.metaglass, 100), () -> {
});
});
node(Blocks.rotaryPump, with(Items.metaglass, 100), () -> {
node(Blocks.thermalPump, with(Items.metaglass, 100), () -> {
});
});
});
node(Blocks.bridgeConduit, with(Items.metaglass, 100));
});
});
});
});
node(Blocks.powerNode, with(Items.copper, 100), () -> {
node(Blocks.combustionGenerator, with(Items.copper, 100), () -> {
node(Blocks.powerNodeLarge, with(Items.copper, 100), () -> {
node(Blocks.battery, with(Items.copper, 100), () -> {
node(Blocks.batteryLarge, with(Items.copper, 100), () -> {
});
});
node(Blocks.mendProjector, with(Items.copper, 100), () -> {
node(Blocks.forceProjector, with(Items.copper, 100), () -> {
node(Blocks.overdriveProjector, with(Items.copper, 100), () -> {
});
});
node(Blocks.repairPoint, with(Items.copper, 100), () -> {
});
});
});
node(Blocks.turbineGenerator, with(Items.copper, 100), () -> {
node(Blocks.thermalGenerator, with(Items.copper, 100), () -> {
node(Blocks.rtgGenerator, with(Items.copper, 100), () -> {
node(Blocks.thoriumReactor, with(Items.copper, 100), () -> {
});
});
});
});
node(Blocks.solarPanel, with(Items.copper, 100), () -> {
node(Blocks.largeSolarPanel, with(Items.copper, 100), () -> {
});
});
});
node(Blocks.alphaPad, with(Items.copper, 100), () -> {
node(Blocks.dartPad, with(Items.copper, 100));
node(Blocks.deltaPad, with(Items.copper, 100), () -> {
node(Blocks.javelinPad, with(Items.copper, 100));
node(Blocks.tauPad, with(Items.copper, 100), () -> {
node(Blocks.tridentPad, with(Items.copper, 100));
node(Blocks.omegaPad, with(Items.copper, 100), () -> {
node(Blocks.glaivePad, with(Items.copper, 100));
});
});
});
node(Blocks.spiritFactory, with(Items.copper, 100), () -> {
node(Blocks.daggerFactory, with(Items.copper, 100), () -> {
node(Blocks.daggerFactory, with(Items.copper, 100), () -> {
node(Blocks.titanFactory, with(Items.copper, 100), () -> {
node(Blocks.fortressFactory, with(Items.copper, 100));
});
node(Blocks.wraithFactory, with(Items.copper, 100), () -> {
node(Blocks.phantomFactory, with(Items.copper, 100));
node(Blocks.ghoulFactory, with(Items.copper, 100), () -> {
node(Blocks.revenantFactory, with(Items.copper, 100));
});
});
});
});
});
});
});
});
}
private TechNode node(Block block, ItemStack[] requirements, Runnable children){
return new TechNode(block, requirements, children);
}
private TechNode node(Block block, ItemStack[] requirements){
return new TechNode(block, requirements, () -> {});
}
private TechNode node(Block block){
return new TechNode(block, with(), () -> {});
} }
public static class TechNode{ public static class TechNode{
static TechNode context;
public final Block block; public final Block block;
public final ItemStack[] requirements; public final ItemStack[] requirements;
public final TechNode[] children; public final Array<TechNode> children = new Array<>();
public TechNode parent;
TechNode(Block block, ItemStack[] requirements, Runnable children){
if(block != null && Recipe.getByResult(block) == null) throw new IllegalArgumentException("Block " + block + " does not have a recipe.");
if(context != null){
context.children.add(this);
}
TechNode(Block block, ItemStack[] requirements, TechNode... children){
this.block = block; this.block = block;
this.requirements = requirements; this.requirements = requirements;
this.children = children;
for(TechNode node : children){ TechNode last = context;
node.parent = this; context = this;
} children.run();
context = last;
} }
} }
} }

View File

@ -68,7 +68,7 @@ public class TreeLayout{
} }
public Rectangle getBounds(){ public Rectangle getBounds(){
return new Rectangle(0, 0, boundsRight - boundsLeft, boundsBottom - boundsTop); return new Rectangle(boundsLeft, boundsBottom, boundsRight - boundsLeft, boundsTop - boundsBottom);
} }
private void calcSizeOfLevels(TreeNode node, int level){ private void calcSizeOfLevels(TreeNode node, int level){

View File

@ -1,6 +1,6 @@
package io.anuke.mindustry.ui.dialogs; package io.anuke.mindustry.ui.dialogs;
import io.anuke.arc.Core; import io.anuke.arc.collection.Array;
import io.anuke.arc.collection.ObjectSet; import io.anuke.arc.collection.ObjectSet;
import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Draw;
import io.anuke.arc.graphics.g2d.Lines; import io.anuke.arc.graphics.g2d.Lines;
@ -12,31 +12,46 @@ import io.anuke.arc.scene.Element;
import io.anuke.arc.scene.event.InputEvent; import io.anuke.arc.scene.event.InputEvent;
import io.anuke.arc.scene.event.InputListener; import io.anuke.arc.scene.event.InputListener;
import io.anuke.arc.util.Log; import io.anuke.arc.util.Log;
import io.anuke.mindustry.Vars; import io.anuke.arc.util.Structs;
import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.content.Blocks;
import io.anuke.mindustry.content.TechTree; import io.anuke.mindustry.content.TechTree;
import io.anuke.mindustry.content.TechTree.TechNode; import io.anuke.mindustry.content.TechTree.TechNode;
import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.type.Recipe;
import io.anuke.mindustry.type.Recipe.RecipeVisibility; import io.anuke.mindustry.type.Recipe.RecipeVisibility;
import io.anuke.mindustry.ui.TreeLayout; import io.anuke.mindustry.ui.TreeLayout;
import io.anuke.mindustry.ui.TreeLayout.TreeNode; import io.anuke.mindustry.ui.TreeLayout.TreeNode;
import io.anuke.mindustry.world.Block.Icon; import io.anuke.mindustry.world.Block.Icon;
import static io.anuke.mindustry.Vars.content;
public class TechTreeDialog extends FloatingDialog{ public class TechTreeDialog extends FloatingDialog{
private TreeLayout layout;
private ObjectSet<TechTreeNode> nodes = new ObjectSet<>(); private ObjectSet<TechTreeNode> nodes = new ObjectSet<>();
private static final float nodeSize = 60f;
public TechTreeDialog(){ public TechTreeDialog(){
super("$techtree"); super("$techtree");
layout = new TreeLayout(); TreeLayout layout = new TreeLayout();
layout.gapBetweenLevels = 60f; layout.gapBetweenLevels = 60f;
layout.gapBetweenNodes = 40f; layout.gapBetweenNodes = 40f;
layout.layout(new TechTreeNode(TechTree.root, null)); layout.layout(new TechTreeNode(TechTree.root, null));
cont.add(new View()).grow(); cont.add(new View()).grow();
double total = Vars.content.recipes().count(r -> r.visibility == RecipeVisibility.all); { //debug code
if(total > nodes.size) Log.err("Recipe tree coverage: {0}%", (int)(nodes.size / total * 100)); ObjectSet<Recipe> used = new ObjectSet<>();
for(TechTreeNode node : nodes){
if(node.node.block != null) used.add(Recipe.getByResult(node.node.block));
}
Array<Recipe> recipes = content.recipes().select(r -> r.visibility == RecipeVisibility.all && !used.contains(r));
recipes.sort(Structs.comparing(r -> r.cost));
if(recipes.size > 0){
Log.info("Recipe tree coverage: {0}%", (int)((float)nodes.size / content.recipes().select(r -> r.visibility == RecipeVisibility.all).size * 100));
Log.info("Missing items: ");
recipes.forEach(r -> Log.info(" {0}", r));
}
}
addCloseButton(); addCloseButton();
} }
@ -47,12 +62,12 @@ public class TechTreeDialog extends FloatingDialog{
public TechTreeNode(TechNode node, TreeNode parent){ public TechTreeNode(TechNode node, TreeNode parent){
this.node = node; this.node = node;
this.parent = parent; this.parent = parent;
this.width = this.height = 60f; this.width = this.height = nodeSize;
nodes.add(this); nodes.add(this);
if(node.children != null){ if(node.children != null){
children = new TechTreeNode[node.children.length]; children = new TechTreeNode[node.children.size];
for(int i = 0; i < children.length; i++){ for(int i = 0; i < children.length; i++){
children[i] = new TechTreeNode(node.children[i], this); children[i] = new TechTreeNode(node.children.get(i), this);
} }
} }
} }
@ -64,15 +79,19 @@ public class TechTreeDialog extends FloatingDialog{
{ {
addListener(new InputListener(){ addListener(new InputListener(){
float lastX, lastY;
@Override @Override
public void touchDragged(InputEvent event, float x, float y, int pointer){ public void touchDragged(InputEvent event, float mx, float my, int pointer){
super.touchDragged(event, x, y, pointer); panX -= lastX - mx;
panX += Core.input.deltaX(pointer); panY -= lastY - my;
panY += Core.input.deltaY(pointer); lastX = mx;
lastY = my;
} }
@Override @Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, KeyCode button){ public boolean touchDown(InputEvent event, float x, float y, int pointer, KeyCode button){
lastX = x;
lastY = y;
return true; return true;
} }
}); });
@ -97,7 +116,7 @@ public class TechTreeDialog extends FloatingDialog{
Draw.color(); Draw.color();
for(TechTreeNode node : nodes){ for(TechTreeNode node : nodes){
Draw.drawable("content-background", node.x + offsetX - node.width/2f, node.y + offsetY - node.height/2f, node.width, node.height); Draw.drawable("content-background", node.x + offsetX - nodeSize/2f, node.y + offsetY - nodeSize/2f, nodeSize, nodeSize);
TextureRegion region = node.node.block == null ? Blocks.core.icon(Icon.medium) : node.node.block.icon(Icon.medium); TextureRegion region = node.node.block == null ? Blocks.core.icon(Icon.medium) : node.node.block.icon(Icon.medium);
Draw.rect(region, node.x + offsetX, node.y + offsetY - 0.5f, region.getWidth(), region.getHeight()); Draw.rect(region, node.x + offsetX, node.y + offsetY - 0.5f, region.getWidth(), region.getHeight());

View File

@ -19,6 +19,18 @@ public class MenuFragment extends Fragment{
@Override @Override
public void build(Group parent){ public void build(Group parent){
if(true){
parent.fill(t -> {
t.add("do not play the bleeding edge").get().setFontScale(2f);
t.row();
t.add("none of it is playable yet");
t.row();
t.add("something usable will be released 'soon' (TM)").get().setFontScale(0.5f);
});
return;
}
parent.fill(c -> { parent.fill(c -> {
container = c; container = c;
container.visible(() -> state.is(State.menu)); container.visible(() -> state.is(State.menu));