diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index f570829f43..76a6f4cfd6 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -575,7 +575,8 @@ uncover = Uncover configure = Configure Loadout objective.research = [accent]Research:\n[]{0}[lightgray]{1} -objective.destroyblock = [accent]Destroy Structure:\n[]{0}[lightgray]{1} +objective.produce = [accent]Obtain:\n[]{0}[lightgray]{1} +objective.destroyblock = [accent]Destroy:\n[]{0}[lightgray]{1} objective.item = [accent]Obtain: [][lightgray]{0}[]/{1}\n{2}[lightgray]{3} objective.coreitem = [accent]Move into Core:\n[][lightgray]{0}[]/{1}\n{2}[lightgray]{3} objective.build = [accent]Build: [][lightgray]{0}[]x\n{1}[lightgray]{2} @@ -703,7 +704,7 @@ sector.planetaryTerminal.description = The final target.\n\nThis coastal base co sector.onset.name = The Onset sector.onset.description = The tutorial sector. This objective has not been created yet. Await further information. -sector.two.description = The enemy is protected by shields. An experimental shield breaker module has been detected in this sector. Find and activate it using tungsten. +sector.two.description = The enemy is protected by shields. An experimental shield breaker module has been detected in this sector.\nLocate this structure. Supply it with tungsten ammunition and destroy the enemy base. status.burning.name = Burning status.freezing.name = Freezing diff --git a/core/assets/maps/two.msav b/core/assets/maps/two.msav index 3d349ff23e..7497076acb 100644 Binary files a/core/assets/maps/two.msav and b/core/assets/maps/two.msav differ diff --git a/core/src/mindustry/ai/RtsAI.java b/core/src/mindustry/ai/RtsAI.java index 6b15a818c5..97368ffd65 100644 --- a/core/src/mindustry/ai/RtsAI.java +++ b/core/src/mindustry/ai/RtsAI.java @@ -32,7 +32,6 @@ public class RtsAI{ //in order of priority?? static final BlockFlag[] flags = {BlockFlag.generator, BlockFlag.factory, BlockFlag.core, BlockFlag.battery}; static final ObjectFloatMap weights = new ObjectFloatMap<>(); - //TODO max squad size static final boolean debug = OS.hasProp("mindustry.debug"); final Interval timer = new Interval(10); diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 84a8b11f8d..043c2318c0 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -4143,10 +4143,10 @@ public class Blocks{ //region units - erekir fabricator = new UnitFactory("fabricator"){{ - requirements(Category.units, with(Items.silicon, 200, Items.beryllium, 250)); + requirements(Category.units, with(Items.silicon, 200, Items.beryllium, 200)); size = 3; configurable = false; - plans.add(new UnitPlan(UnitTypes.stell, 60f * 60f * 1f, with(Items.beryllium, 50f, Items.silicon, 60f))); + plans.add(new UnitPlan(UnitTypes.stell, 60f * 45f * 1f, with(Items.beryllium, 50f, Items.silicon, 60f))); researchCost = with(Items.beryllium, 200, Items.graphite, 80, Items.silicon, 80); regionSuffix = "-dark"; fogRadius = 3; diff --git a/core/src/mindustry/content/SectorPresets.java b/core/src/mindustry/content/SectorPresets.java index c53c2a74fd..56b5f28da1 100644 --- a/core/src/mindustry/content/SectorPresets.java +++ b/core/src/mindustry/content/SectorPresets.java @@ -2,6 +2,7 @@ package mindustry.content; import mindustry.game.MapObjectives.*; import mindustry.game.Team; +import mindustry.graphics.*; import mindustry.type.*; import static mindustry.content.Planets.*; @@ -186,12 +187,15 @@ public class SectorPresets{ rules = r -> { r.objectives.addAll( - new TimerObjective("Enemy detection", 5 * 60 * 60).withMarkers( - new TextMarker("The enemy will begin constructing units in 5 minutes.", 276f * 8f, 164f * 8f) + new TimerObjective("[lightgray]Enemy detection:[] [accent]{0}", 5 * 60 * 60).withMarkers( + new TextMarker("The enemy will begin constructing units in 5 minutes.", 276f * 8f, 164f * 8f) ).withFlags("beginBuilding"), + new ProduceObjective(Items.tungsten).withMarkers( + new ShapeTextMarker("Tungsten can be mined using an [accent]impact drill[].\nThis structure requires [accent]water[] and [accent]power[].", 220f * 8f, 181f * 8f) + ), new DestroyBlockObjective(Blocks.largeShieldProjector, 210, 278, Team.malis).withMarkers( - new TextMarker("The enemy is protected by shields.\nAn experimental shield breaker module has been detected in this sector.\nFind and activate it using tungsten.", 276f * 8f, 164f * 8f), - new ShapeTextMarker("Tungsten can be mined using an [accent]impact drill[].\nIt requires water.", 220f * 8f, 181f * 8f) + new TextMarker("The enemy is protected by shields.\nAn experimental shield breaker module has been detected in this sector.\nFind and activate it using tungsten.", 276f * 8f, 164f * 8f), + new MinimapMarker(23f, 137f, Pal.accent) ) ); }; diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index b5031900be..ce05ab12da 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -2878,7 +2878,7 @@ public class UnitTypes{ smoothReloadSpeed = 0.15f; recoil = 2f; - bullet = new BasicBulletType(3.5f, 50){{ + bullet = new BasicBulletType(3.5f, 55){{ backColor = trailColor = hitColor = Pal.techBlue; frontColor = Color.white; width = 7.5f; @@ -3323,7 +3323,7 @@ public class UnitTypes{ shoot = new ShootHelix(); //TODO cooler + balancing - bullet = new BasicBulletType(5f, 25){{ + bullet = new BasicBulletType(5f, 30){{ width = 7f; height = 12f; lifetime = 25f; diff --git a/core/src/mindustry/core/Control.java b/core/src/mindustry/core/Control.java index e254d98fb1..09241d4a97 100644 --- a/core/src/mindustry/core/Control.java +++ b/core/src/mindustry/core/Control.java @@ -211,16 +211,17 @@ public class Control implements ApplicationListener, Loadable{ if(state.isCampaign()){ - //TODO add a delay for landing. if(state.rules.sector.planet.prebuildBase){ float unitsPerTick = 1f; + float buildRadius = state.rules.enemyCoreBuildRadius * 1.5f; + //TODO if the save is unloaded, these blocks do not get built. boolean anyBuilds = false; for(var build : state.rules.defaultTeam.data().buildings.copy()){ if(!(build instanceof CoreBuild) && !build.block.privileged){ var ccore = build.closestCore(); - if(ccore != null && build.within(ccore, state.rules.enemyCoreBuildRadius)){ + if(ccore != null && build.within(ccore, buildRadius)){ build.pickedUp(); build.tile.remove(); anyBuilds = true; @@ -242,7 +243,7 @@ public class Control implements ApplicationListener, Loadable{ if(anyBuilds){ for(var ccore : state.rules.defaultTeam.data().cores){ Time.run(coreDelay, () -> { - Fx.coreBuildShockwave.at(ccore.x, ccore.y, state.rules.enemyCoreBuildRadius); + Fx.coreBuildShockwave.at(ccore.x, ccore.y, buildRadius); }); } } diff --git a/core/src/mindustry/game/MapObjectives.java b/core/src/mindustry/game/MapObjectives.java index 625e0c002c..2a2da4dd2b 100644 --- a/core/src/mindustry/game/MapObjectives.java +++ b/core/src/mindustry/game/MapObjectives.java @@ -20,7 +20,7 @@ public class MapObjectives{ public static Prov[] allObjectiveTypes = new Prov[]{ ResearchObjective::new, BuildCountObjective::new, UnitCountObjective::new, ItemObjective::new, CommandModeObjective::new, CoreItemObjective::new, DestroyCoreObjective::new, DestroyUnitsObjective::new, - TimerObjective::new, FlagObjective::new, DestroyBlockObjective::new + TimerObjective::new, FlagObjective::new, DestroyBlockObjective::new, ProduceObjective::new }; public static Prov[] allMarkerTypes = new Prov[]{ @@ -49,6 +49,28 @@ public class MapObjectives{ } } + /** Produce a specific piece of content in the tech tree (essentially research with different text). */ + public static class ProduceObjective extends MapObjective{ + public UnlockableContent content = Items.copper; + + public ProduceObjective(UnlockableContent content){ + this.content = content; + } + + public ProduceObjective(){ + } + + @Override + public String text(){ + return Core.bundle.format("objective.produce", content.emoji(), content.localizedName); + } + + @Override + public boolean complete(){ + return content.unlocked(); + } + } + /** Have a certain amount of item in your core. */ public static class ItemObjective extends MapObjective{ public Item item = Items.copper; @@ -432,6 +454,12 @@ public class MapObjectives{ this.y = y; } + public MinimapMarker(float x, float y, Color color){ + this.x = x; + this.y = y; + this.color = color; + } + public MinimapMarker(){ } diff --git a/core/src/mindustry/ui/fragments/BlockInventoryFragment.java b/core/src/mindustry/ui/fragments/BlockInventoryFragment.java index d67403ca61..2e92791074 100644 --- a/core/src/mindustry/ui/fragments/BlockInventoryFragment.java +++ b/core/src/mindustry/ui/fragments/BlockInventoryFragment.java @@ -28,7 +28,7 @@ public class BlockInventoryFragment{ private static final float holdShrink = 120f; Table table = new Table(); - Building tile; + Building build; float holdTime = 0f, emptyTime; boolean holding, held; float[] shrinkHoldTimes = new float[content.items().size]; @@ -46,13 +46,14 @@ public class BlockInventoryFragment{ } public void showFor(Building t){ - if(this.tile == t){ + if(this.build == t){ hide(); return; } - this.tile = t; - if(tile == null || !tile.block.isAccessible() || tile.items.total() == 0) + this.build = t; + if(build == null || !build.block.isAccessible() || build.items == null || build.items.total() == 0){ return; + } rebuild(true); } @@ -65,7 +66,7 @@ public class BlockInventoryFragment{ table.update(null); }), Actions.visible(false)); table.touchable = Touchable.disabled; - tile = null; + build = null; } private void takeItem(int requested){ @@ -73,12 +74,12 @@ public class BlockInventoryFragment{ int amount = Math.min(requested, player.unit().maxAccepted(lastItem)); if(amount > 0){ - Call.requestItem(player, tile, lastItem, amount); + Call.requestItem(player, build, lastItem, amount); holding = false; holdTime = 0f; held = true; - if(net.client()) Events.fire(new WithdrawEvent(tile, player, lastItem, amount)); + if(net.client()) Events.fire(new WithdrawEvent(build, player, lastItem, amount)); } } @@ -94,10 +95,10 @@ public class BlockInventoryFragment{ table.touchable = Touchable.enabled; table.update(() -> { - if(state.isMenu() || tile == null || !tile.isValid() || !tile.block.isAccessible() || emptyTime >= holdShrink){ + if(state.isMenu() || build == null || !build.isValid() || !build.block.isAccessible() || emptyTime >= holdShrink){ hide(); }else{ - if(tile.items.total() == 0){ + if(build.items.total() == 0){ emptyTime += Time.delta; }else{ emptyTime = 0f; @@ -111,12 +112,12 @@ public class BlockInventoryFragment{ } updateTablePosition(); - if(tile.block.hasItems){ + if(build.block.hasItems){ boolean dirty = false; if(shrinkHoldTimes.length != content.items().size) shrinkHoldTimes = new float[content.items().size]; for(int i = 0; i < content.items().size; i++){ - boolean has = tile.items.has(content.item(i)); + boolean has = build.items.has(content.item(i)); boolean had = container.contains(i); if(has){ shrinkHoldTimes[i] = 0f; @@ -141,28 +142,28 @@ public class BlockInventoryFragment{ table.margin(4f); table.defaults().size(8 * 5).pad(4f); - if(tile.block.hasItems){ + if(build.block.hasItems){ for(int i = 0; i < content.items().size; i++){ Item item = content.item(i); - if(!tile.items.has(item)) continue; + if(!build.items.has(item)) continue; container.add(i); - Boolp canPick = () -> player.unit().acceptsItem(item) && !state.isPaused() && player.within(tile, itemTransferRange); + Boolp canPick = () -> player.unit().acceptsItem(item) && !state.isPaused() && player.within(build, itemTransferRange); HandCursorListener l = new HandCursorListener(); l.enabled = canPick; Element image = itemImage(item.uiIcon, () -> { - if(tile == null || !tile.isValid()){ + if(build == null || !build.isValid()){ return ""; } - return round(tile.items.get(item)); + return round(build.items.get(item)); }); image.addListener(l); - Boolp validClick = () -> !(!canPick.get() || tile == null || !tile.isValid() || tile.items == null || !tile.items.has(item)); + Boolp validClick = () -> !(!canPick.get() || build == null || !build.isValid() || build.items == null || !build.items.has(item)); image.addListener(new ClickListener(){ @@ -182,7 +183,7 @@ public class BlockInventoryFragment{ if(!validClick.get() || held) return; //take all - takeItem(tile.items.get(lastItem = item)); + takeItem(build.items.get(lastItem = item)); } @Override @@ -227,7 +228,7 @@ public class BlockInventoryFragment{ } private void updateTablePosition(){ - Vec2 v = Core.input.mouseScreen(tile.x + tile.block.size * tilesize / 2f, tile.y + tile.block.size * tilesize / 2f); + Vec2 v = Core.input.mouseScreen(build.x + build.block.size * tilesize / 2f, build.y + build.block.size * tilesize / 2f); table.pack(); table.setPosition(v.x, v.y, Align.topLeft); }