diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 84eba8e14a..52feed8ca2 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -69,7 +69,7 @@ stat.delivered = Resources Launched: stat.playtime = Time Played:[accent] {0} stat.rank = Final Rank: [accent]{0} -globalitems = [accent]Global Items +globalitems = [accent]Total Items map.delete = Are you sure you want to delete the map "[accent]{0}[]"? level.highscore = High Score: [accent]{0} level.select = Level Select @@ -1282,6 +1282,7 @@ hint.generator = \uf879 [accent]Combustion Generators[] burn coal and transmit p hint.guardian = [accent]Guardian[] units are armored. Weak ammo such as [accent]Copper[] and [accent]Lead[] is [scarlet]not effective[].\n\nUse higher tier turrets or \uf835 [accent]Graphite[] \uf861Duo/\uf859Salvo ammunition to take Guardians down. hint.coreUpgrade = Cores can be upgraded by [accent]placing higher-tier cores over them[].\n\nPlace a  [accent]Foundation[] core over the  [accent]Shard[] core. Make sure it is free from nearby obstructions. hint.presetLaunch = Gray [accent]landing zone sectors[], such as [accent]Frozen Forest[], can be launched to from anywhere. They do not require capture of nearby territory.\n\n[accent]Numbered sectors[], such as this one, are [accent]optional[]. +hint.coreIncinerate = After the core is filled to capacity with an item, any extra items of that type it receives will be [accent]incinerated[]. item.copper.description = Used in all types of construction and ammunition. item.copper.details = Copper. Abnormally abundant metal on Serpulo. Structurally weak unless reinforced. diff --git a/core/src/mindustry/ctype/UnlockableContent.java b/core/src/mindustry/ctype/UnlockableContent.java index 9a87e622b4..3ee5ac1ba8 100644 --- a/core/src/mindustry/ctype/UnlockableContent.java +++ b/core/src/mindustry/ctype/UnlockableContent.java @@ -6,6 +6,8 @@ import arc.graphics.g2d.*; import arc.scene.ui.layout.*; import arc.util.*; import mindustry.annotations.Annotations.*; +import mindustry.content.*; +import mindustry.content.TechTree.*; import mindustry.game.EventType.*; import mindustry.graphics.*; import mindustry.type.*; @@ -42,6 +44,11 @@ public abstract class UnlockableContent extends MappableContent{ this.unlocked = Core.settings != null && Core.settings.getBool(this.name + "-unlocked", false); } + /** @return the tech node for this content. may be null. */ + public @Nullable TechNode node(){ + return TechTree.get(this); + } + public String displayDescription(){ return minfo.mod == null ? description : description + "\n" + Core.bundle.format("mod.display", minfo.mod.meta.displayName()); } diff --git a/core/src/mindustry/ui/dialogs/PlanetDialog.java b/core/src/mindustry/ui/dialogs/PlanetDialog.java index 9c298a9dc6..6df80b6311 100644 --- a/core/src/mindustry/ui/dialogs/PlanetDialog.java +++ b/core/src/mindustry/ui/dialogs/PlanetDialog.java @@ -15,8 +15,10 @@ import arc.scene.ui.layout.*; import arc.struct.*; import arc.util.*; import mindustry.content.*; +import mindustry.content.TechTree.*; import mindustry.core.*; import mindustry.ctype.*; +import mindustry.game.Objectives.*; import mindustry.game.SectorInfo.*; import mindustry.game.*; import mindustry.gen.*; @@ -253,7 +255,10 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ boolean canSelect(Sector sector){ if(mode == select) return sector.hasBase(); //preset sectors can only be selected once unlocked - if(sector.preset != null) return sector.preset.unlocked() || sector.hasBase(); + if(sector.preset != null){ + TechNode node = sector.preset.node(); + return node == null || node.parent == null || node.parent.content.unlocked(); + } return sector.hasBase() || sector.near().contains(Sector::hasBase); //near an occupied sector } @@ -291,7 +296,9 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ Color color = sec.hasBase() ? Tmp.c2.set(Team.sharded.color).lerp(Team.crux.color, sec.hasEnemyBase() ? 0.5f : 0f) : - sec.preset != null ? Tmp.c2.set(Team.derelict.color).lerp(Color.white, Mathf.absin(Time.time, 10f, 1f)) : + sec.preset != null ? + sec.preset.unlocked() ? Tmp.c2.set(Team.derelict.color).lerp(Color.white, Mathf.absin(Time.time, 10f, 1f)) : + Color.gray : sec.hasEnemyBase() ? Team.crux.color : null; @@ -352,7 +359,12 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ for(Sector sec : planet.sectors){ if(sec != hovered){ var preficon = sec.icon(); - var icon = (sec.isAttacked() ? Fonts.getLargeIcon("warning") : !sec.hasBase() && sec.preset != null && sec.preset.unlocked() && preficon == null ? Fonts.getLargeIcon("terrain") : preficon); + var icon = + sec.isAttacked() ? Fonts.getLargeIcon("warning") : + !sec.hasBase() && sec.preset != null && sec.preset.unlocked() && preficon == null ? + Fonts.getLargeIcon("terrain") : + sec.preset != null && sec.preset.locked() && sec.preset.node() != null && !sec.preset.node().parent.content.locked() ? Fonts.getLargeIcon("lock") : + preficon; var color = sec.preset != null && !sec.hasBase() ? Team.derelict.color : Team.sharded.color; if(icon != null){ @@ -690,7 +702,21 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ stable.image().color(Pal.accent).fillX().height(3f).pad(3f).row(); - if(!sector.hasBase()){ + boolean locked = sector.preset != null && sector.preset.locked() && sector.preset.node() != null; + + if(locked){ + stable.table(r -> { + r.add("@complete").colspan(2).left(); + r.row(); + for(Objective o : sector.preset.node().objectives){ + if(o.complete()) continue; + + r.add("> " + o.display()).color(Color.lightGray).left(); + r.image(o.complete() ? Icon.ok : Icon.cancel, o.complete() ? Color.lightGray : Color.scarlet).padLeft(3); + r.row(); + } + }).row(); + }else if(!sector.hasBase()){ stable.add(Core.bundle.get("sectors.threat") + " [accent]" + sector.displayThreat()).row(); } @@ -730,13 +756,23 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ } if((sector.hasBase() && mode == look) || canSelect(sector) || (sector.preset != null && sector.preset.alwaysUnlocked) || debugSelect){ - stable.button(mode == select ? "@sectors.select" : sector.isBeingPlayed() ? "@sectors.resume" : sector.hasBase() ? "@sectors.go" : "@sectors.launch", Icon.play, () -> { + stable.button( + mode == select ? "@sectors.select" : + sector.isBeingPlayed() ? "@sectors.resume" : + sector.hasBase() ? "@sectors.go" : + locked ? "@locked" : "@sectors.launch", + locked ? Icon.lock :Icon.play, () -> { + if(sector.isBeingPlayed()){ //already at this sector hide(); return; } + if(sector.preset != null && sector.preset.locked()){ + return; + } + boolean shouldHide = true; //save before launch. @@ -778,7 +814,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ } if(shouldHide) hide(); - }).growX().height(54f).minWidth(170f).padTop(4); + }).growX().height(54f).minWidth(170f).padTop(4).disabled(locked); } stable.pack(); diff --git a/core/src/mindustry/ui/fragments/HintsFragment.java b/core/src/mindustry/ui/fragments/HintsFragment.java index da0d6a05d2..7c7892b8ac 100644 --- a/core/src/mindustry/ui/fragments/HintsFragment.java +++ b/core/src/mindustry/ui/fragments/HintsFragment.java @@ -172,6 +172,7 @@ public class HintsFragment extends Fragment{ && SectorPresets.frozenForest.unlocked() && SectorPresets.frozenForest.sector.save == null, () -> state.isCampaign() && state.getSector().preset == SectorPresets.frozenForest), + coreIncinerate(() -> state.isCampaign() && state.rules.defaultTeam.core() != null && state.rules.defaultTeam.core().items.get(Items.copper) >= state.rules.defaultTeam.core().storageCapacity - 10, () -> false), ; @Nullable diff --git a/tests/src/test/java/ApplicationTests.java b/tests/src/test/java/ApplicationTests.java index 7ae2a1a090..866f2d032e 100644 --- a/tests/src/test/java/ApplicationTests.java +++ b/tests/src/test/java/ApplicationTests.java @@ -5,6 +5,7 @@ import arc.math.*; import arc.math.geom.*; import arc.struct.*; import arc.util.*; +import arc.util.Log.*; import mindustry.*; import mindustry.content.*; import mindustry.core.*; @@ -52,11 +53,13 @@ public class ApplicationTests{ return 0; } }; + Log.info("creating base content"); content.createBaseContent(); add(logic = new Logic()); add(netServer = new NetServer()); + Log.info("initializing content"); content.init(); } @@ -494,8 +497,9 @@ public class ApplicationTests{ @Test void buildingOverlap(){ - Log.info("Testing buildingOverlap, initialized = @", initialized); - + Log.level = LogLevel.debug; + Log.info("log content"); + Vars.content.logContent(); initBuilding(); Unit d1 = UnitTypes.poly.create(Team.sharded); @@ -525,8 +529,8 @@ public class ApplicationTests{ void buildingDestruction(){ initBuilding(); - Builderc d1 = (Builderc)UnitTypes.poly.create(Team.sharded); - Builderc d2 = (Builderc)UnitTypes.poly.create(Team.sharded); + Builderc d1 = UnitTypes.poly.create(Team.sharded); + Builderc d2 = UnitTypes.poly.create(Team.sharded); d1.set(10f, 20f); d2.set(10f, 20f);