diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index bbf99f9fca..47cdc0e3aa 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -1724,25 +1724,22 @@ team.blue.name = Blue hint.skip = Skip hint.desktopMove = Use [accent][[WASD][] to move. hint.zoom = [accent]Scroll[] to zoom in or out. -hint.mine = Move near the \uF8C4 copper ore and [accent]tap[] it to mine manually. hint.desktopShoot = [accent][[Left-click][] to shoot. hint.depositItems = To transfer items, drag from your ship to the core. hint.respawn = To respawn as a ship, press [accent][[V][]. hint.respawn.mobile = You have switched control to a unit/structure. To respawn as a ship, [accent]tap the avatar in the top left.[] hint.desktopPause = Press [accent][[Space][] to pause and unpause the game. -hint.placeDrill = Select the \uE85E [accent]Drill[] tab in the menu at the bottom right, then select a \uF870 [accent]Drill[] and click on a copper patch to place it. -hint.placeDrill.mobile = Select the \uE85E [accent]Drill[] tab in the menu at the bottom right, then select a \uF870 [accent]Drill[] and tap on a copper patch to place it.\n\nPress the \uE800 [accent]checkmark[] at the bottom right to confirm. -hint.placeConveyor = Conveyors move items from drills into other blocks. Select a \uF896 [accent]Conveyor[] from the \uE814 [accent]Distribution[] tab.\n\nClick and drag to place multiple conveyors.\n[accent]Scroll[] to rotate. -hint.placeConveyor.mobile = Conveyors move items from drills into other blocks. Select a \uF896 [accent]Conveyor[] from the \uE814 [accent]Distribution[] tab.\n\nHold down your finger for a second and drag to place multiple conveyors. -hint.placeTurret = Place \uF861 [accent]Turrets[] to defend your base from enemies.\n\nTurrets require ammo - in this case, \uF838copper.\nUse conveyors and drills to supply them. + hint.breaking = [accent]Right-click[] and drag to break blocks. hint.breaking.mobile = Activate the \uE817 [accent]hammer[] in the bottom right and tap to break blocks.\n\nHold down your finger for a second and drag to break in a selection. hint.blockInfo = View information of a block by selecting it in the [accent]build menu[], then selecting the [accent][[?][] button at the right. hint.derelict = [accent]Derelict[] structures are broken remnants of old bases that no longer function.\n\nThese structures can be [accent]deconstructed[] for resources. hint.research = Use the \uE875 [accent]Research[] button to research new technology. hint.research.mobile = Use the \uE875 [accent]Research[] button in the \uE88C [accent]Menu[] to research new technology. -hint.unitControl = Hold [accent][[L-ctrl][] and [accent]click[] to control friendly units or turrets. -hint.unitControl.mobile = [accent][[Double-tap][] to control friendly units or turrets. +hint.unitControl = Hold [accent][[L-ctrl][] and [accent]click[] to manually control friendly units or turrets. +hint.unitControl.mobile = [accent][[Double-tap][] to manually control friendly units or turrets. +hint.unitSelectControl = To control units, enter [accent]command mode[] by holding [accent]L-shift.[]\nWhile in command mode, click and drag to select units. [accent]Right-click[] a location or target to command units there. +hint.unitSelectControl.mobile = To control units, enter [accent]command mode[] by pressing the [accent]command[] button in the bottom left.\nWhile in command mode, long-press and drag to select units. Tap a location or target to command units there. hint.launch = Once enough resources are collected, you can [accent]Launch[] by selecting nearby sectors from the \uE827 [accent]Map[] in the bottom right. hint.launch.mobile = Once enough resources are collected, you can [accent]Launch[] by selecting nearby sectors from the \uE827 [accent]Map[] in the \uE88C [accent]Menu[]. hint.schematicSelect = Hold [accent][[F][] and drag to select blocks to copy and paste.\n\n[accent][[Middle Click][] to copy a single block type. @@ -1763,6 +1760,29 @@ hint.coreIncinerate = After the core is filled to capacity with an item, any ext hint.factoryControl = To set a unit factory's [accent]output destination[], click a factory block while in command mode, then right-click a location.\nUnits produced by it will automatically move there. hint.factoryControl.mobile = To set a unit factory's [accent]output destination[], tap a factory block while in command mode, then tap a location.\nUnits produced by it will automatically move there. +gz.mine = Move near the \uf8c4 [accent]copper ore[] on the ground and click to begin mining. +gz.mine.mobile = Move near the \uf8c4 [accent]copper ore[] on the ground and tap it to begin mining. + +gz.research = Open the \ue875 tech tree.\nResearch the \uf870 [accent]Mechanical Drill[], then select it from the menu in the bottom right.\nClick on a copper patch to place it. +gz.research.mobile = Open the \ue875 tech tree.\nResearch the \uf870 [accent]Mechanical Drill[], then select it from the menu in the bottom right.\nTap on a copper patch to place it.\n\nPress the \uE800 [accent]checkmark[] at the bottom right to confirm. + +gz.conveyors = Research and place \uf896 [accent]conveyors[] to move the mined resources\nfrom drills to the core.\n\nClick and drag to place multiple conveyors.\n[accent]Scroll[] to rotate. +gz.conveyors.mobile = Research and place \uf896 [accent]conveyors[] to move the mined resources\nfrom drills to the core.\n\nHold down your finger for a second and drag to place multiple conveyors. + +gz.drills = Expand the mining operation.\nPlace more Mechanical Drills.\nMine 100 copper. +gz.lead = \uf837 [accent]Lead[] is another commonly used resource.\nSet up drills to mine lead. + +gz.moveup = \ue804 Move up for further objectives. +gz.turrets = Research and place 2 \uf861 [accent]Duo[] turrets to defend the core.\nDuo turrets require \uf838 [accent]ammo[] from conveyors. +gz.walls = [accent]Walls[] can prevent oncoming damage from reaching buildings.\nPlace \uf8ae [accent]copper walls[] around the turrets. +gz.defend = Enemy incoming, prepare to defend. +gz.aa = Flying units cannot easily be dispatched with standard turrets.\n\uf860 [accent]Scatter[] turrets provide excellent anti-air, but require \uf837 [accent]lead[] as ammo. +gz.zone1 = This is the enemy drop zone. +gz.zone2 = Anything built in the radius is destroyed when a wave starts. +gz.zone3 = A wave will begin now.\nGet ready. +gz.finish = Build more turrets, mine more resources,\nand defend against all the waves to [accent]capture the sector[]. + + item.copper.description = Used in all types of construction and ammunition. item.copper.details = Copper. Abnormally abundant metal on Serpulo. Structurally weak unless reinforced. item.lead.description = Used in liquid transportation and electrical structures. diff --git a/core/assets/maps/groundZero.msav b/core/assets/maps/groundZero.msav index bb169dbbc7..34fe213016 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 26102dbebb..33d8ec6cd1 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -1503,6 +1503,7 @@ public class Blocks{ copperWall = new Wall("copper-wall"){{ requirements(Category.defense, with(Items.copper, 6)); health = 80 * wallHealthMultiplier; + researchCostMultiplier = 0.1f; envDisabled |= Env.scorching; }}; @@ -1886,11 +1887,12 @@ public class Blocks{ //region distribution conveyor = new Conveyor("conveyor"){{ - requirements(Category.distribution, with(Items.copper, 1), true); + requirements(Category.distribution, with(Items.copper, 1)); health = 45; speed = 0.03f; displayedSpeed = 4.2f; buildCostMultiplier = 2f; + researchCost = with(Items.copper, 5); }}; titaniumConveyor = new Conveyor("titanium-conveyor"){{ @@ -1915,7 +1917,7 @@ public class Blocks{ }}; junction = new Junction("junction"){{ - requirements(Category.distribution, with(Items.copper, 2), true); + requirements(Category.distribution, with(Items.copper, 2)); speed = 26; capacity = 6; health = 30; @@ -2639,12 +2641,13 @@ public class Blocks{ //region production mechanicalDrill = new Drill("mechanical-drill"){{ - requirements(Category.production, with(Items.copper, 12), true); + requirements(Category.production, with(Items.copper, 12)); tier = 2; drillTime = 600; size = 2; //mechanical drill doesn't work in space envEnabled ^= Env.space; + researchCost = with(Items.copper, 10); consumeLiquid(Liquids.water, 0.05f).boost(); }}; @@ -3002,7 +3005,7 @@ public class Blocks{ //region turrets duo = new ItemTurret("duo"){{ - requirements(Category.turret, with(Items.copper, 35), true); + requirements(Category.turret, with(Items.copper, 35)); ammo( Items.copper, new BasicBulletType(2.5f, 9){{ width = 7f; @@ -3038,6 +3041,7 @@ public class Blocks{ inaccuracy = 2f; rotateSpeed = 10f; coolant = consumeCoolant(0.1f); + researchCostMultiplier = 0.05f; limitRange(); }}; @@ -3105,6 +3109,7 @@ public class Blocks{ scaledHealth = 200; shootSound = Sounds.shootSnap; coolant = consumeCoolant(0.2f); + researchCostMultiplier = 0.05f; limitRange(2); }}; diff --git a/core/src/mindustry/content/Items.java b/core/src/mindustry/content/Items.java index 8d79830c11..9b963bf4c0 100644 --- a/core/src/mindustry/content/Items.java +++ b/core/src/mindustry/content/Items.java @@ -23,7 +23,6 @@ public class Items{ lead = new Item("lead", Color.valueOf("8c7fa9")){{ hardness = 1; cost = 0.7f; - alwaysUnlocked = true; }}; metaglass = new Item("metaglass", Color.valueOf("ebeef5")){{ @@ -36,8 +35,9 @@ public class Items{ sand = new Item("sand", Color.valueOf("f7cba4")){{ lowPriority = true; - alwaysUnlocked = true; buildable = false; + //needed to show up as requirement + alwaysUnlocked = true; }}; coal = new Item("coal", Color.valueOf("272727")){{ diff --git a/core/src/mindustry/content/SectorPresets.java b/core/src/mindustry/content/SectorPresets.java index af8a2a3e4c..a474e4bf70 100644 --- a/core/src/mindustry/content/SectorPresets.java +++ b/core/src/mindustry/content/SectorPresets.java @@ -22,6 +22,7 @@ public class SectorPresets{ addStartingItems = true; captureWave = 10; difficulty = 1; + overrideLaunchDefaults = true; startWaveTimeMultiplier = 3f; }}; diff --git a/core/src/mindustry/game/MapObjectives.java b/core/src/mindustry/game/MapObjectives.java index b642d9eb24..fcc7e521f4 100644 --- a/core/src/mindustry/game/MapObjectives.java +++ b/core/src/mindustry/game/MapObjectives.java @@ -680,7 +680,7 @@ public class MapObjectives implements Iterable, Eachable Core.input.axis(Binding.move_x) != 0 || Core.input.axis(Binding.move_y) != 0), zoom(visibleDesktop, () -> Core.input.axis(KeyCode.scroll) != 0), - mine(() -> player.unit().canMine() && isTutorial.get(), () -> player.unit().mining()), - placeDrill(isTutorial, () -> ui.hints.placedBlocks.contains(Blocks.mechanicalDrill)), - placeConveyor(isTutorial, () -> ui.hints.placedBlocks.contains(Blocks.conveyor)), - placeTurret(isTutorial, () -> ui.hints.placedBlocks.contains(Blocks.duo)), - breaking(isTutorial, () -> ui.hints.events.contains("break")), + breaking(() -> isTutorial.get() && state.rules.defaultTeam.data().getCount(Blocks.conveyor) > 5, () -> ui.hints.events.contains("break")), desktopShoot(visibleDesktop, () -> isSerpulo() && Vars.state.enemies > 0, () -> player.shooting), depositItems(() -> player.unit().hasItem(), () -> !player.unit().hasItem()), - desktopPause(visibleDesktop, () -> isTutorial.get() && !Vars.net.active(), () -> Core.input.keyTap(Binding.pause)), - research(isTutorial, () -> ui.research.isShown()), + desktopPause(visibleDesktop, () -> isTutorial.get() && !Vars.net.active() && state.wave >= 2, () -> Core.input.keyTap(Binding.pause)), unitControl(() -> isSerpulo() && state.rules.defaultTeam.data().units.size > 2 && !net.active() && !player.dead(), () -> !player.dead() && !player.unit().spawnedByCore), + unitSelectControl(() -> isSerpulo() && state.rules.defaultTeam.data().units.size > 3 && !net.active() && !player.dead(), () -> control.input.commandMode && control.input.selectedUnits.size > 0), respawn(visibleMobile, () -> !player.dead() && !player.unit().spawnedByCore, () -> !player.dead() && player.unit().spawnedByCore), launch(() -> isTutorial.get() && state.rules.sector.isCaptured(), () -> ui.planet.isShown()), - schematicSelect(visibleDesktop, () -> ui.hints.placedBlocks.contains(Blocks.router), () -> Core.input.keyRelease(Binding.schematic_select) || Core.input.keyTap(Binding.pick)), + schematicSelect(visibleDesktop, () -> ui.hints.placedBlocks.contains(Blocks.router) || ui.hints.placedBlocks.contains(Blocks.ductRouter), () -> Core.input.keyRelease(Binding.schematic_select) || Core.input.keyTap(Binding.pick)), conveyorPathfind(() -> control.input.block == Blocks.titaniumConveyor, () -> Core.input.keyRelease(Binding.diagonal_placement) || (mobile && Core.settings.getBool("swapdiagonal"))), boost(visibleDesktop, () -> !player.dead() && player.unit().type.canBoost, () -> Core.input.keyDown(Binding.boost)), blockInfo(() -> !(state.isCampaign() && state.rules.sector == SectorPresets.groundZero.sector && state.wave < 3), () -> ui.content.isShown()), diff --git a/tests/src/test/java/ApplicationTests.java b/tests/src/test/java/ApplicationTests.java index 2e2f0b968c..1160fea462 100644 --- a/tests/src/test/java/ApplicationTests.java +++ b/tests/src/test/java/ApplicationTests.java @@ -393,6 +393,7 @@ public class ApplicationTests{ void liquidOutput(){ world.loadMap(testMap); state.set(State.playing); + state.rules.limitMapArea = false; world.tile(0, 0).setBlock(Blocks.liquidSource, Team.sharded); world.tile(0, 0).build.configureAny(Liquids.water); @@ -409,6 +410,7 @@ public class ApplicationTests{ void liquidJunctionOutput(){ world.loadMap(testMap); state.set(State.playing); + state.rules.limitMapArea = false; Tile source = world.rawTile(0, 0), tank = world.rawTile(1, 4), junction = world.rawTile(0, 1), conduit = world.rawTile(0, 2); @@ -431,9 +433,10 @@ public class ApplicationTests{ void liquidRouterOutputAll() { world.loadMap(testMap); state.set(State.playing); + state.rules.limitMapArea = false; Tile source = world.rawTile(4,0), router = world.rawTile(4, 2), conduitUp1 = world.rawTile(4,1), - conduitLeft = world.rawTile(3,2), conduitUp2 = world.rawTile(4, 3), conduitRight = world.rawTile(5, 2), - leftTank = world.rawTile(1, 2), topTank = world.rawTile(4,5), rightTank = world.rawTile(7, 2); + conduitLeft = world.rawTile(3,2), conduitUp2 = world.rawTile(4, 3), conduitRight = world.rawTile(5, 2), + leftTank = world.rawTile(1, 2), topTank = world.rawTile(4,5), rightTank = world.rawTile(7, 2); source.setBlock(Blocks.liquidSource, Team.sharded); source.build.configureAny(Liquids.water); @@ -456,10 +459,11 @@ public class ApplicationTests{ void sorterOutputCorrect() { world.loadMap(testMap); state.set(State.playing); + state.rules.limitMapArea = false; Tile source1 = world.rawTile(4, 0), source2 = world.rawTile(6, 0), s1conveyor = world.rawTile(4, 1), - s2conveyor = world.rawTile(6, 1), s1s2conveyor = world.rawTile(5, 1), sorter = world.rawTile(5, 2), - leftconveyor = world.rawTile(4, 2), rightconveyor = world.rawTile(6, 2), sortedconveyor = world.rawTile(5, 3), - leftVault = world.rawTile(2, 2), rightVault = world.rawTile(8, 2), topVault = world.rawTile(5, 5); + s2conveyor = world.rawTile(6, 1), s1s2conveyor = world.rawTile(5, 1), sorter = world.rawTile(5, 2), + leftconveyor = world.rawTile(4, 2), rightconveyor = world.rawTile(6, 2), sortedconveyor = world.rawTile(5, 3), + leftVault = world.rawTile(2, 2), rightVault = world.rawTile(8, 2), topVault = world.rawTile(5, 5); source1.setBlock(Blocks.itemSource, Team.sharded); source1.build.configureAny(Items.coal); @@ -488,10 +492,11 @@ public class ApplicationTests{ void routerOutputAll() { world.loadMap(testMap); state.set(State.playing); + state.rules.limitMapArea = false; Tile source1 = world.rawTile(5, 0), conveyor = world.rawTile(5, 1), - router = world.rawTile(5, 2), leftconveyor = world.rawTile(4, 2), rightconveyor = world.rawTile(6, 2), - middleconveyor = world.rawTile(5, 3), leftVault = world.rawTile(2, 2), - rightVault = world.rawTile(8, 2), topVault = world.rawTile(5, 5); + router = world.rawTile(5, 2), leftconveyor = world.rawTile(4, 2), rightconveyor = world.rawTile(6, 2), + middleconveyor = world.rawTile(5, 3), leftVault = world.rawTile(2, 2), + rightVault = world.rawTile(8, 2), topVault = world.rawTile(5, 5); source1.setBlock(Blocks.itemSource, Team.sharded); source1.build.configureAny(Items.coal); @@ -515,9 +520,10 @@ public class ApplicationTests{ void junctionOutputCorrect() { world.loadMap(testMap); state.set(State.playing); + state.rules.limitMapArea = false; Tile source1 = world.rawTile(5,0),source2 = world.rawTile(7, 2), conveyor1 = world.rawTile(5, 1), - conveyor2 = world.rawTile(6,2), junction = world.rawTile(5, 2), conveyor3 = world.rawTile(5,3), - conveyor4 = world.rawTile(4,2), vault2 = world.rawTile(3, 1), vault1 = world.rawTile(5,5); + conveyor2 = world.rawTile(6,2), junction = world.rawTile(5, 2), conveyor3 = world.rawTile(5,3), + conveyor4 = world.rawTile(4,2), vault2 = world.rawTile(3, 1), vault1 = world.rawTile(5,5); source1.setBlock(Blocks.itemSource, Team.sharded); source1.build.configureAny(Items.coal); source2.setBlock(Blocks.itemSource, Team.sharded); @@ -565,6 +571,7 @@ public class ApplicationTests{ world.loadMap(testMap); state.set(State.playing); + state.rules.limitMapArea = false; int length = 128; world.tile(0, 0).setBlock(Blocks.itemSource, Team.sharded); world.tile(0, 0).build.configureAny(Items.copper); @@ -873,7 +880,6 @@ public class ApplicationTests{ Time.setDeltaProvider(() -> 1f); logic.reset(); - state.rules.sector = zone.sector; try{ world.loadGenerator(zone.generator.map.width, zone.generator.map.height, zone.generator::generate); }catch(SaveException e){ @@ -934,6 +940,7 @@ public class ApplicationTests{ } assertEquals(1, Team.sharded.cores().size, "Sector must have one core: " + zone); + assertTrue(Team.sharded.core().items.total() < 1000, "Sector must not have starting resources: " + zone); assertTrue(hasSpawnPoint, "Sector \"" + zone.name + "\" has no spawn points."); assertTrue(spawner.countSpawns() > 0 || (state.rules.attackMode && state.rules.waveTeam.data().hasCore()), "Sector \"" + zone.name + "\" has no enemy spawn points: " + spawner.countSpawns()); @@ -975,4 +982,4 @@ public class ApplicationTests{ tile.build.handleStack(item, 1, unit); assertEquals(capacity, tile.build.items.get(item)); } -} +} \ No newline at end of file