diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index eef7dd7e26..a323537cc3 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -486,6 +486,7 @@ complete = [lightgray]Complete: requirement.wave = Reach Wave {0} in {1} requirement.core = Destroy Enemy Core in {0} requirement.research = Research {0} +requirement.produce = Produce {0} requirement.capture = Capture {0} bestwave = [lightgray]Best Wave: {0} launch.text = Launch diff --git a/core/assets/maps/biomassFacility.msav b/core/assets/maps/biomassFacility.msav index 37132355e2..bf16a3b7ea 100644 Binary files a/core/assets/maps/biomassFacility.msav and b/core/assets/maps/biomassFacility.msav differ diff --git a/core/assets/maps/craters.msav b/core/assets/maps/craters.msav index 04c1aa73d3..c1e5959997 100644 Binary files a/core/assets/maps/craters.msav and b/core/assets/maps/craters.msav differ diff --git a/core/assets/maps/impact0078.msav b/core/assets/maps/impact0078.msav index 77a3bd96c3..56f5570bfb 100644 Binary files a/core/assets/maps/impact0078.msav and b/core/assets/maps/impact0078.msav differ diff --git a/core/assets/maps/stainedMountains.msav b/core/assets/maps/stainedMountains.msav index c627b0917e..af3abb26c2 100644 Binary files a/core/assets/maps/stainedMountains.msav and b/core/assets/maps/stainedMountains.msav differ diff --git a/core/src/mindustry/ClientLauncher.java b/core/src/mindustry/ClientLauncher.java index 213f465156..3777da85c7 100644 --- a/core/src/mindustry/ClientLauncher.java +++ b/core/src/mindustry/ClientLauncher.java @@ -46,7 +46,6 @@ public abstract class ClientLauncher extends ApplicationCore implements Platform //debug GL information Log.info("[GL] Version: @", graphics.getGLVersion()); Log.info("[GL] Max texture size: @", Gl.getInt(Gl.maxTextureSize)); - Log.info("[GL] Max vert/frag shader FP precision: @ / @", Gl.getShaderPrecision(Gl.vertexShader, Gl.highFloat), Gl.getShaderPrecision(Gl.fragmentShader, Gl.highFloat)); Log.info("[GL] Using @ context.", gl30 != null ? "OpenGL 3" : "OpenGL 2"); Log.info("[JAVA] Version: @", System.getProperty("java.version")); diff --git a/core/src/mindustry/content/SectorPresets.java b/core/src/mindustry/content/SectorPresets.java index e6ff587048..808905f967 100644 --- a/core/src/mindustry/content/SectorPresets.java +++ b/core/src/mindustry/content/SectorPresets.java @@ -48,7 +48,7 @@ public class SectorPresets implements ContentList{ windsweptIslands = new SectorPreset("windsweptIslands", serpulo, 246){{ captureWave = 30; - difficulty = 5; + difficulty = 4; }}; stainedMountains = new SectorPreset("stainedMountains", serpulo, 20){{ diff --git a/core/src/mindustry/content/TechTree.java b/core/src/mindustry/content/TechTree.java index 77e5344e05..a7796f9c41 100644 --- a/core/src/mindustry/content/TechTree.java +++ b/core/src/mindustry/content/TechTree.java @@ -11,7 +11,6 @@ import static mindustry.content.Blocks.*; import static mindustry.content.SectorPresets.craters; import static mindustry.content.SectorPresets.*; import static mindustry.content.UnitTypes.*; -import static mindustry.type.ItemStack.*; public class TechTree implements ContentList{ static ObjectMap map = new ObjectMap<>(); @@ -40,9 +39,9 @@ public class TechTree implements ContentList{ node(underflowGate); }); }); - node(container, () -> { + node(container, Seq.with(new SectorComplete(biomassFacility)), () -> { node(unloader); - node(vault, () -> { + node(vault, Seq.with(new SectorComplete(stainedMountains)), () -> { }); }); @@ -108,185 +107,152 @@ public class TechTree implements ContentList{ }); }); - node(Items.coal, with(Items.lead, 3000), () -> { - node(Items.graphite, with(Items.coal, 1000), () -> { + node(graphitePress, () -> { + node(pneumaticDrill, () -> { + node(cultivator, Seq.with(new SectorComplete(biomassFacility)), () -> { - node(graphitePress, () -> { - node(Items.titanium, with(Items.graphite, 3000, Items.copper, 7000, Items.lead, 7000), () -> { - node(pneumaticDrill, () -> { - node(Items.sporePod, with(Items.coal, 4000, Items.graphite, 4000, Items.lead, 4000), () -> { - node(cultivator, Seq.with(new SectorComplete(biomassFacility)), () -> { + }); - }); - }); + node(laserDrill, () -> { + node(blastDrill, () -> { - node(Items.thorium, with(Items.titanium, 8000, Items.lead, 12000, Items.copper, 20000), () -> { - node(laserDrill, () -> { - node(blastDrill, () -> { - - }); - - node(waterExtractor, () -> { - node(oilExtractor, () -> { - - }); - }); - }); - }); - }); }); - node(Items.pyratite, with(Items.coal, 6000, Items.lead, 8000, Items.sand, 4000), () -> { - node(pyratiteMixer, () -> { - node(Items.blastCompound, with(Items.pyratite, 3000, Items.sporePod, 3000), () -> { - node(blastMixer, () -> { + node(waterExtractor, () -> { + node(oilExtractor, () -> { - }); - }); }); }); - - node(Items.silicon, with(Items.coal, 3000, Items.sand, 4000), () -> { - node(siliconSmelter, () -> { - - node(Liquids.oil, with(Items.coal, 8000, Items.pyratite, 6000, Items.sand, 8000), () -> { - node(sporePress, () -> { - node(coalCentrifuge, () -> { - node(multiPress, () -> { - node(siliconCrucible, () -> { - - }); - }); - }); - - node(Items.plastanium, with(Items.titanium, 8000, Items.silicon, 8000), () -> { - node(plastaniumCompressor, () -> { - node(Items.phaseFabric, with(Items.thorium, 12000, Items.sand, 8000, Items.silicon, 5000), () -> { - node(phaseWeaver, () -> { - - }); - }); - }); - }); - }); - }); - - node(Items.metaglass, with(Items.sand, 4000, Items.lead, 10000), () -> { - node(kiln, () -> { - node(incinerator, () -> { - node(Items.scrap, with(Items.copper, 8000, Items.sand, 4000), () -> { - node(Liquids.slag, with(Items.scrap, 4000), () -> { - node(melter, () -> { - node(Items.surgeAlloy, with(Items.thorium, 20000, Items.silicon, 20000, Items.lead, 40000), () -> { - node(surgeSmelter, () -> { - - }); - }); - - node(separator, () -> { - node(pulverizer, () -> { - node(disassembler, () -> { - - }); - }); - }); - - node(Liquids.cryofluid, with(Items.titanium, 8000, Items.metaglass, 4000), () -> { - node(cryofluidMixer, () -> { - - }); - }); - }); - }); - }); - }); - }); - }); - - node(microProcessor, () -> { - node(switchBlock, () -> { - node(message, () -> { - node(logicDisplay, () -> { - node(largeLogicDisplay, () -> { - - }); - }); - - node(memoryCell, () -> { - node(memoryBank, () -> { - - }); - }); - }); - - node(logicProcessor, () -> { - node(hyperProcessor, () -> { - - }); - }); - }); - }); - }); - }); - - node(illuminator, () -> { - }); }); }); + node(pyratiteMixer, () -> { + node(blastMixer, () -> { - node(combustionGenerator, () -> { - node(powerNode, () -> { - node(powerNodeLarge, () -> { - node(diode, () -> { - node(surgeTower, () -> { + }); + }); + + node(siliconSmelter, () -> { + + node(sporePress, () -> { + node(coalCentrifuge, () -> { + node(multiPress, () -> { + node(siliconCrucible, () -> { }); }); }); - node(battery, () -> { - node(batteryLarge, () -> { + node(plastaniumCompressor, () -> { + node(phaseWeaver, () -> { }); }); + }); - node(mender, () -> { - node(mendProjector, () -> { - node(forceProjector, () -> { - node(overdriveProjector, () -> { - node(overdriveDome, () -> { + node(kiln, Seq.with(new SectorComplete(craters)), () -> { + node(incinerator, () -> { + node(melter, () -> { + node(surgeSmelter, () -> { + + }); + + node(separator, () -> { + node(pulverizer, () -> { + node(disassembler, () -> { }); }); }); - node(repairPoint, () -> { + node(cryofluidMixer, () -> { }); }); }); + }); - node(steamGenerator, () -> { - node(thermalGenerator, () -> { - node(differentialGenerator, () -> { - node(thoriumReactor, Seq.with(new Research(Liquids.cryofluid)), () -> { - node(impactReactor, () -> { + node(microProcessor, () -> { + node(switchBlock, () -> { + node(message, () -> { + node(logicDisplay, () -> { + node(largeLogicDisplay, () -> { - }); + }); + }); - node(rtgGenerator, () -> { + node(memoryCell, () -> { + node(memoryBank, () -> { + + }); + }); + }); + + node(logicProcessor, () -> { + node(hyperProcessor, () -> { + + }); + }); + }); + }); + }); + + node(illuminator, () -> { + }); + }); + + + node(combustionGenerator, Seq.with(new Research(Items.coal)), () -> { + node(powerNode, () -> { + node(powerNodeLarge, () -> { + node(diode, () -> { + node(surgeTower, () -> { + + }); + }); + }); + + node(battery, () -> { + node(batteryLarge, () -> { + + }); + }); + + node(mender, () -> { + node(mendProjector, () -> { + node(forceProjector, Seq.with(new SectorComplete(impact0078)), () -> { + node(overdriveProjector, Seq.with(new SectorComplete(impact0078)), () -> { + node(overdriveDome, Seq.with(new SectorComplete(impact0078)), () -> { + + }); + }); + }); + + node(repairPoint, () -> { + + }); + }); + }); + + node(steamGenerator, () -> { + node(thermalGenerator, () -> { + node(differentialGenerator, () -> { + node(thoriumReactor, Seq.with(new Research(Liquids.cryofluid)), () -> { + node(impactReactor, () -> { + + }); + + node(rtgGenerator, () -> { - }); }); }); }); }); + }); - node(solarPanel, () -> { - node(largeSolarPanel, () -> { + node(solarPanel, () -> { + node(largeSolarPanel, () -> { - }); }); }); }); @@ -321,8 +287,7 @@ public class TechTree implements ContentList{ }); node(scatter, () -> { - node(hail, () -> { - + node(hail, Seq.with(new SectorComplete(craters)), () -> { node(salvo, () -> { node(swarmer, () -> { node(cyclone, () -> { @@ -451,7 +416,7 @@ public class TechTree implements ContentList{ }); }); - node(additiveReconstructor, () -> { + node(additiveReconstructor, Seq.with(new SectorComplete(biomassFacility)), () -> { node(multiplicativeReconstructor, () -> { node(exponentialReconstructor, () -> { node(tetrativeReconstructor, () -> { @@ -525,6 +490,7 @@ public class TechTree implements ContentList{ new SectorComplete(fungalPass), new Research(cultivator), new Research(sporePress), + new Research(additiveReconstructor), new Research(UnitTypes.mace), new Research(UnitTypes.flare) ), () -> { @@ -562,6 +528,63 @@ public class TechTree implements ContentList{ }); }); }); + + nodeProduce(Items.copper, () -> { + nodeProduce(Items.lead, () -> { + nodeProduce(Items.graphite, () -> { + nodeProduce(Items.titanium, () -> { + nodeProduce(Liquids.cryofluid, () -> { + + }); + + nodeProduce(Items.thorium, () -> { + nodeProduce(Items.surgeAlloy, () -> { + + }); + + nodeProduce(Items.phaseFabric, () -> { + + }); + }); + }); + }); + + nodeProduce(Items.metaglass, () -> { + + }); + }); + + nodeProduce(Items.sand, () -> { + nodeProduce(Items.scrap, () -> { + nodeProduce(Liquids.slag, () -> { + + }); + }); + + nodeProduce(Items.coal, () -> { + nodeProduce(Items.silicon, () -> { + + }); + nodeProduce(Items.pyratite, () -> { + nodeProduce(Items.blastCompound, () -> { + + }); + }); + + nodeProduce(Items.sporePod, () -> { + + }); + + nodeProduce(Liquids.oil, () -> { + + }); + }); + }); + + nodeProduce(Liquids.water, () -> { + + }); + }); }); } @@ -604,6 +627,14 @@ public class TechTree implements ContentList{ return node(block, () -> {}); } + static TechNode nodeProduce(UnlockableContent content, Seq objectives, Runnable children){ + return node(content, content.researchRequirements(), objectives.and(new Produce(content)), children); + } + + static TechNode nodeProduce(UnlockableContent content, Runnable children){ + return nodeProduce(content, new Seq<>(), children); + } + @Nullable public static TechNode get(UnlockableContent content){ return map.get(content); diff --git a/core/src/mindustry/core/Control.java b/core/src/mindustry/core/Control.java index 946c675605..f0aeed065e 100644 --- a/core/src/mindustry/core/Control.java +++ b/core/src/mindustry/core/Control.java @@ -11,6 +11,7 @@ import arc.struct.*; import arc.util.*; import mindustry.audio.*; import mindustry.content.*; +import mindustry.content.TechTree.*; import mindustry.core.GameState.*; import mindustry.entities.*; import mindustry.game.EventType.*; @@ -127,6 +128,14 @@ public class Control implements ApplicationListener, Loadable{ Events.on(UnlockEvent.class, e -> ui.hudfrag.showUnlock(e.content)); + Events.on(UnlockEvent.class, e -> { + checkAutoUnlocks(); + }); + + Events.on(SectorCaptureEvent.class, e -> { + checkAutoUnlocks(); + }); + Events.on(BlockBuildEndEvent.class, e -> { if(e.team == player.team()){ if(e.breaking){ @@ -177,6 +186,7 @@ public class Control implements ApplicationListener, Loadable{ app.post(() -> Fx.coreLand.at(core.getX(), core.getY(), 0, core.block)); camera.position.set(core); player.set(core); + Time.run(Fx.coreLand.lifetime, () -> { Fx.launch.at(core); Effect.shake(5f, 5f, core); @@ -209,6 +219,17 @@ public class Control implements ApplicationListener, Loadable{ saves.load(); } + /** Automatically unlocks things with no requirements. */ + void checkAutoUnlocks(){ + if(net.client()) return; + + for(TechNode node : TechTree.all){ + if(!node.content.unlocked() && node.requirements.length == 0 && !node.objectives.contains(o -> !o.complete())){ + node.content.unlocked(); + } + } + } + void createPlayer(){ player = Player.create(); player.name = Core.settings.getString("name"); @@ -520,6 +541,12 @@ public class Control implements ApplicationListener, Loadable{ platform.updateRPC(); } + //unlock core items + var core = state.rules.defaultTeam.core(); + if(!net.client() && core != null){ + core.items.each((i, a) -> i.unlock()); + } + if(Core.input.keyTap(Binding.pause) && !scene.hasDialog() && !scene.hasKeyboard() && !ui.restart.isShown() && (state.is(State.paused) || state.is(State.playing))){ state.set(state.is(State.playing) ? State.paused : State.playing); } diff --git a/core/src/mindustry/editor/EditorTile.java b/core/src/mindustry/editor/EditorTile.java index 8283b39159..e4be334888 100644 --- a/core/src/mindustry/editor/EditorTile.java +++ b/core/src/mindustry/editor/EditorTile.java @@ -76,6 +76,8 @@ public class EditorTile extends Tile{ if(getTeamID() == team.id) return; op(OpType.team, (byte)getTeamID()); super.setTeam(team); + + getLinkedTiles(t -> ui.editor.editor.renderer.updatePoint(t.x, t.y)); } @Override diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index f9094e1461..facc17c40b 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -519,6 +519,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, public void dumpLiquid(Liquid liquid){ int dump = this.cdump; + if(!net.client()) liquid.unlock(); + for(int i = 0; i < proximity.size; i++){ incrementDump(proximity.size); Building other = proximity.get((i + dump) % proximity.size); @@ -618,6 +620,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, */ public void offload(Item item){ int dump = this.cdump; + if(!net.client()) item.unlock(); for(int i = 0; i < proximity.size; i++){ incrementDump(proximity.size); diff --git a/core/src/mindustry/game/Objectives.java b/core/src/mindustry/game/Objectives.java index 7faa162624..acf7fad876 100644 --- a/core/src/mindustry/game/Objectives.java +++ b/core/src/mindustry/game/Objectives.java @@ -28,6 +28,26 @@ public class Objectives{ } } + public static class Produce implements Objective{ + public UnlockableContent content; + + public Produce(UnlockableContent content){ + this.content = content; + } + + protected Produce(){} + + @Override + public boolean complete(){ + return content.unlocked(); + } + + @Override + public String display(){ + return Core.bundle.format("requirement.produce", content.emoji() + " " + content.localizedName); + } + } + public static class SectorComplete extends SectorObjective{ public SectorComplete(SectorPreset zone){ diff --git a/core/src/mindustry/world/Block.java b/core/src/mindustry/world/Block.java index 0e3e459340..392827be9d 100644 --- a/core/src/mindustry/world/Block.java +++ b/core/src/mindustry/world/Block.java @@ -617,7 +617,7 @@ public class Block extends UnlockableContent{ public ItemStack[] researchRequirements(){ ItemStack[] out = new ItemStack[requirements.length]; for(int i = 0; i < out.length; i++){ - int quantity = 60 + Mathf.round(Mathf.pow(requirements[i].amount, 1.11f) * 20 * researchCostMultiplier, 10); + int quantity = 60 + Mathf.round(Mathf.pow(requirements[i].amount, 1.13f) * 20 * researchCostMultiplier, 10); out[i] = new ItemStack(requirements[i].item, UI.roundAmount(quantity)); } @@ -631,6 +631,19 @@ public class Block extends UnlockableContent{ for(ItemStack stack : requirements){ cons.get(stack.item); } + + if(consumes.any()){ + //also requires inputs + for(Consume c : consumes.all()){ + if(c instanceof ConsumeItems i){ + for(ItemStack stack : i.items){ + cons.get(stack.item); + } + }else if(c instanceof ConsumeLiquid i){ + cons.get(i.liquid); + } + } + } } @Override diff --git a/core/src/mindustry/world/consumers/Consumers.java b/core/src/mindustry/world/consumers/Consumers.java index a811a24d52..ee0c76a2a7 100644 --- a/core/src/mindustry/world/consumers/Consumers.java +++ b/core/src/mindustry/world/consumers/Consumers.java @@ -101,6 +101,7 @@ public class Consumers{ return (T)map[type.ordinal()]; } + @Nullable public Consume[] all(){ return results; } diff --git a/gradle.properties b/gradle.properties index 6ea4b5fa59..5c751c2d61 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ org.gradle.daemon=true org.gradle.jvmargs=-Xms256m -Xmx1024m -archash=e430136d6c6f14a1254e1bcde427ec3b334e3cbd +archash=1c7e02ed2e2059ee1fca6812fb0d2ffd860f82b3