diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 7dcad61ea1..3ec02254de 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -570,7 +570,11 @@ configure = Configure Loadout objective.research = [accent]Research:\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} +objective.buildunit = [accent]Build Unit: [][lightgray]{0}[]x\n{1}[lightgray]{2} +objective.destroycore = [accent]Destroy Enemy Core +objective.command = [accent]Command Units loadout = Loadout resources = Resources diff --git a/core/src/mindustry/content/SectorPresets.java b/core/src/mindustry/content/SectorPresets.java index 55e1a6ea9f..c284bbd32e 100644 --- a/core/src/mindustry/content/SectorPresets.java +++ b/core/src/mindustry/content/SectorPresets.java @@ -122,7 +122,9 @@ public class SectorPresets{ new ResearchObjective(Blocks.turbineCondenser), new BuildCountObjective(Blocks.turbineCondenser, 1).withMarkers( new ShapeTextMarker("Place a [accent]turbine condenser[] on the vent.\nThis will generate [accent]power[].", 253f * 8f, 258f * 8f, 8f * 2.6f, 0f, 9f) - )); + ), + new CoreItemObjective(Items.graphite, 10) + ); }; }}; diff --git a/core/src/mindustry/game/GameStats.java b/core/src/mindustry/game/GameStats.java index 964b3fd9cd..a96fd80f8e 100644 --- a/core/src/mindustry/game/GameStats.java +++ b/core/src/mindustry/game/GameStats.java @@ -1,6 +1,7 @@ package mindustry.game; import arc.struct.*; +import mindustry.type.*; import mindustry.world.*; public class GameStats{ @@ -18,4 +19,9 @@ public class GameStats{ public int unitsCreated; /** Record of blocks that have been placed by count. Used for objectives only. */ public ObjectIntMap placedBlockCount = new ObjectIntMap<>(); + /** + * Record of items that have entered the core through transport blocks. Used for objectives only. + * This can easily be ""spoofed"" with unloaders, so don't use it for anything remotely important. + * */ + public ObjectIntMap coreItemCount = new ObjectIntMap<>(); } diff --git a/core/src/mindustry/game/MapObjectives.java b/core/src/mindustry/game/MapObjectives.java index 85e77c1421..485af7962d 100644 --- a/core/src/mindustry/game/MapObjectives.java +++ b/core/src/mindustry/game/MapObjectives.java @@ -5,7 +5,6 @@ import arc.func.*; import arc.graphics.*; import arc.graphics.g2d.*; import arc.util.*; -import mindustry.*; import mindustry.content.*; import mindustry.ctype.*; import mindustry.gen.*; @@ -13,15 +12,19 @@ import mindustry.graphics.*; import mindustry.type.*; import mindustry.world.*; +import static mindustry.Vars.*; + public class MapObjectives{ public static Prov[] allObjectiveTypes = new Prov[]{ - ResearchObjective::new, BuildCountObjective::new, ItemObjective::new + ResearchObjective::new, BuildCountObjective::new, UnitCountObjective::new, ItemObjective::new, + CommandModeObjective::new, CoreItemObjective::new, DestroyCoreObjective::new }; public static Prov[] allMarkerTypes = new Prov[]{ TextMarker::new, ShapeMarker::new, ShapeTextMarker::new }; + /** Research a specific piece of content in the tech tree. */ public static class ResearchObjective extends MapObjective{ public UnlockableContent content = Items.copper; @@ -41,13 +44,9 @@ public class MapObjectives{ public boolean complete(){ return content.unlocked(); } - - @Override - public @Nullable String details(){ - return super.details(); - } } + /** Have a certain amount of item in your core. */ public static class ItemObjective extends MapObjective{ public Item item = Items.copper; public int amount = 1; @@ -62,22 +61,49 @@ public class MapObjectives{ @Override public String text(){ - return Core.bundle.format("objective.item", Vars.state.rules.defaultTeam.items().get(item), amount, item.emoji(), item.localizedName); + return Core.bundle.format("objective.item", state.rules.defaultTeam.items().get(item), amount, item.emoji(), item.localizedName); } @Override public boolean complete(){ - return Vars.state.rules.defaultTeam.items().has(item, amount); + return state.rules.defaultTeam.items().has(item, amount); } } + /** Get a certain item in your core (through a block, not manually.) */ + public static class CoreItemObjective extends MapObjective{ + public Item item = Items.copper; + public int amount = 2; + + public CoreItemObjective(Item item, int amount){ + this.item = item; + this.amount = amount; + } + + public CoreItemObjective(){ + } + + + + @Override + public String text(){ + return Core.bundle.format("objective.coreitem", state.stats.coreItemCount.get(item), amount, item.emoji(), item.localizedName); + } + + @Override + public boolean complete(){ + return state.stats.coreItemCount.get(item) >= amount; + } + } + + /** Build a certain amount of a block. */ public static class BuildCountObjective extends MapObjective{ public Block block = Blocks.conveyor; - public int placeCount = 1; + public int count = 1; - public BuildCountObjective(Block block, int placeCount){ + public BuildCountObjective(Block block, int count){ this.block = block; - this.placeCount = placeCount; + this.count = count; } public BuildCountObjective(){ @@ -85,23 +111,82 @@ public class MapObjectives{ @Override public String text(){ - return Core.bundle.format("objective.build", placeCount, block.emoji(), block.localizedName); + return Core.bundle.format("objective.build", count, block.emoji(), block.localizedName); } @Override public boolean complete(){ - return Vars.state.stats.placedBlockCount.get(block, 0) >= placeCount; + return state.stats.placedBlockCount.get(block, 0) >= count; } } + /** Produce a certain amount of a unit. */ + public static class UnitCountObjective extends MapObjective{ + public UnitType unit = UnitTypes.dagger; + public int count = 1; + + public UnitCountObjective(UnitType unit, int count){ + this.unit = unit; + this.count = count; + } + + public UnitCountObjective(){ + } + + @Override + public String text(){ + return Core.bundle.format("objective.buildunit", unit, unit.emoji(), unit.localizedName); + } + + @Override + public boolean complete(){ + return state.rules.defaultTeam.data().countType(unit) >= count; + } + } + + /** Command any unit to do anything. Always compete in headless mode. */ + public static class CommandModeObjective extends MapObjective{ + + @Override + public String text(){ + return Core.bundle.get("objective.command"); + } + + @Override + public boolean complete(){ + return headless || control.input.selectedUnits.contains(u -> u.isCommandable() && u.command().hasCommand()); + } + } + + /** Destroy all enemy core(s). */ + public static class DestroyCoreObjective extends MapObjective{ + + @Override + public String text(){ + return Core.bundle.get("objective.destroycore"); + } + + @Override + public boolean complete(){ + return state.rules.waveTeam.cores().size == 0; + } + } + + /** Base abstract class for any in-map objective. */ public static abstract class MapObjective{ public ObjectiveMarker[] markers = {}; + public @Nullable String details; public MapObjective withMarkers(ObjectiveMarker... markers){ this.markers = markers; return this; } + public MapObjective withDetails(String details){ + this.details = details; + return this; + } + public boolean complete(){ return false; } @@ -127,12 +212,13 @@ public class MapObjectives{ /** Details that appear upon click. */ public @Nullable String details(){ - return null; + return details; } } + /** Displays text above a shape. */ public static class ShapeTextMarker extends ObjectiveMarker{ - public String text = "sample text"; + public String text = "frog"; public float x, y, fontSize = 1f, textHeight = 7f; public byte flags = WorldLabel.flagBackground | WorldLabel.flagOutline; @@ -186,6 +272,7 @@ public class MapObjectives{ } } + /** Displays a shape with an outline and color. */ public static class ShapeMarker extends ObjectiveMarker{ public float x, y, radius = 6f, rotation = 0f; public int sides = 4; @@ -216,6 +303,7 @@ public class MapObjectives{ } } + /** Displays text at a location. */ public static class TextMarker extends ObjectiveMarker{ public String text = "uwu"; public float x, y, fontSize = 1f; diff --git a/core/src/mindustry/world/blocks/storage/CoreBlock.java b/core/src/mindustry/world/blocks/storage/CoreBlock.java index 4c35723103..707276b377 100644 --- a/core/src/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/mindustry/world/blocks/storage/CoreBlock.java @@ -500,6 +500,10 @@ public class CoreBlock extends StorageBlock{ state.rules.sector.info.handleCoreItem(item, 1); } + if(team == state.rules.defaultTeam){ + state.stats.coreItemCount.increment(item); + } + if(items.get(item) >= storageCapacity || incinerate){ //create item incineration effect at random intervals if(!noEffect){