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,
//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
spiritFactory, phantomFactory, wraithFactory, ghoulFactory, revenantFactory, daggerFactory, titanFactory,
@ -787,15 +787,6 @@ public class Blocks implements ContentList{
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"){{
ammo(
Liquids.water, Bullets.waterShot,

View File

@ -1,7 +1,9 @@
package io.anuke.mindustry.content;
import io.anuke.arc.collection.Array;
import io.anuke.mindustry.game.ContentList;
import io.anuke.mindustry.type.ItemStack;
import io.anuke.mindustry.type.Recipe;
import io.anuke.mindustry.world.Block;
import static io.anuke.mindustry.type.ItemStack.with;
@ -11,43 +13,273 @@ public class TechTree implements ContentList{
@Override
public void load(){
root = new TechNode(null, with(),
new TechNode(Blocks.copperWall, with(Items.copper, 100),
new TechNode(Blocks.copperWallLarge, with(Items.copper, 100))
),
root = node(null, with(), () -> {
new TechNode(Blocks.conveyor, with(Items.copper, 10),
new TechNode(Blocks.router, with(Items.copper, 10),
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))
),
node(Blocks.conveyor, with(Items.copper, 100), () -> {
node(Blocks.launchPad, with(Items.copper, 100), () -> {
new TechNode(Blocks.conduit, with(Items.metaglass, 10),
new TechNode(Blocks.liquidJunction, with(Items.metaglass, 10)),
new TechNode(Blocks.liquidRouter, with(Items.metaglass, 10),
new TechNode(Blocks.liquidTank, with(Items.metaglass, 10))
)
)
);
});
node(Blocks.junction, with(Items.copper, 100), () -> {
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{
static TechNode context;
public final Block block;
public final ItemStack[] requirements;
public final TechNode[] children;
public TechNode parent;
public final Array<TechNode> children = new Array<>();
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.requirements = requirements;
this.children = children;
for(TechNode node : children){
node.parent = this;
}
TechNode last = context;
context = this;
children.run();
context = last;
}
}
}

View File

@ -68,7 +68,7 @@ public class TreeLayout{
}
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){

View File

@ -1,6 +1,6 @@
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.graphics.g2d.Draw;
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.InputListener;
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.TechTree;
import io.anuke.mindustry.content.TechTree.TechNode;
import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.type.Recipe;
import io.anuke.mindustry.type.Recipe.RecipeVisibility;
import io.anuke.mindustry.ui.TreeLayout;
import io.anuke.mindustry.ui.TreeLayout.TreeNode;
import io.anuke.mindustry.world.Block.Icon;
import static io.anuke.mindustry.Vars.content;
public class TechTreeDialog extends FloatingDialog{
private TreeLayout layout;
private ObjectSet<TechTreeNode> nodes = new ObjectSet<>();
private static final float nodeSize = 60f;
public TechTreeDialog(){
super("$techtree");
layout = new TreeLayout();
TreeLayout layout = new TreeLayout();
layout.gapBetweenLevels = 60f;
layout.gapBetweenNodes = 40f;
layout.layout(new TechTreeNode(TechTree.root, null));
cont.add(new View()).grow();
double total = Vars.content.recipes().count(r -> r.visibility == RecipeVisibility.all);
if(total > nodes.size) Log.err("Recipe tree coverage: {0}%", (int)(nodes.size / total * 100));
{ //debug code
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();
}
@ -47,12 +62,12 @@ public class TechTreeDialog extends FloatingDialog{
public TechTreeNode(TechNode node, TreeNode parent){
this.node = node;
this.parent = parent;
this.width = this.height = 60f;
this.width = this.height = nodeSize;
nodes.add(this);
if(node.children != null){
children = new TechTreeNode[node.children.length];
children = new TechTreeNode[node.children.size];
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(){
float lastX, lastY;
@Override
public void touchDragged(InputEvent event, float x, float y, int pointer){
super.touchDragged(event, x, y, pointer);
panX += Core.input.deltaX(pointer);
panY += Core.input.deltaY(pointer);
public void touchDragged(InputEvent event, float mx, float my, int pointer){
panX -= lastX - mx;
panY -= lastY - my;
lastX = mx;
lastY = my;
}
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, KeyCode button){
lastX = x;
lastY = y;
return true;
}
});
@ -97,7 +116,7 @@ public class TechTreeDialog extends FloatingDialog{
Draw.color();
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);
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
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 -> {
container = c;
container.visible(() -> state.is(State.menu));