diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 586c31752e..85385e8900 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -176,6 +176,10 @@ filename = File Name: unlocked = New content unlocked! available = New research available! unlock.incampaign = < Unlock in campaign for details > +campaign.select = Select Starting Campaign +campaign.none = [lightgray]Select a planet to start on.\nThis can be switched at any time. +campaign.erekir = [accent]Recommended for new players.[]\n\nNewer, more polished content. Mostly linear campaign progression.\n\nHigher quality maps and overall experience. +campaign.serpulo = [scarlet]Not recommended for new players.[]\n\nOlder content; the classic experience. More open-ended.\n\nPotentially unbalanced maps and campaign mechanics. Less polished. completed = [accent]Completed techtree = Tech Tree techtree.select = Tech Tree Selection diff --git a/core/assets/maps/erekirwavemap.msav b/core/assets/maps/erekirwavemap.msav index 51ccd0d166..fc2ce40a0a 100644 Binary files a/core/assets/maps/erekirwavemap.msav and b/core/assets/maps/erekirwavemap.msav differ diff --git a/core/assets/sprites/planets/erekir.png b/core/assets/sprites/planets/erekir.png new file mode 100644 index 0000000000..f3e887205a Binary files /dev/null and b/core/assets/sprites/planets/erekir.png differ diff --git a/core/assets/sprites/planets/serpulo.png b/core/assets/sprites/planets/serpulo.png new file mode 100644 index 0000000000..b90097673e Binary files /dev/null and b/core/assets/sprites/planets/serpulo.png differ diff --git a/core/src/mindustry/content/Planets.java b/core/src/mindustry/content/Planets.java index 05ae825513..deed729ab5 100644 --- a/core/src/mindustry/content/Planets.java +++ b/core/src/mindustry/content/Planets.java @@ -64,6 +64,7 @@ public class Planets{ lightDstFrom = 0.2f; clearSectorOnLose = true; defaultCore = Blocks.coreBastion; + iconColor = Color.valueOf("ff9266"); hiddenItems.addAll(Items.serpuloItems).removeAll(Items.erekirItems); //TODO SHOULD there be lighting? @@ -140,6 +141,7 @@ public class Planets{ r.attributes.clear(); r.showSpawns = false; }; + iconColor = Color.valueOf("7d4dff"); atmosphereColor = Color.valueOf("3c1b8f"); atmosphereRadIn = 0.02f; atmosphereRadOut = 0.3f; diff --git a/core/src/mindustry/type/Planet.java b/core/src/mindustry/type/Planet.java index 4ecb8fc586..4299382597 100644 --- a/core/src/mindustry/type/Planet.java +++ b/core/src/mindustry/type/Planet.java @@ -89,6 +89,8 @@ public class Planet extends UnlockableContent{ public Color lightColor = Color.white.cpy(); /** Atmosphere tint for landable planets. */ public Color atmosphereColor = new Color(0.3f, 0.7f, 1.0f); + /** Icon for appearance in planet list. */ + public Color iconColor = Color.white.cpy(); /** Whether this planet has an atmosphere. */ public boolean hasAtmosphere = true; /** Whether to allow users to specify a custom launch schematic for this map. */ @@ -107,6 +109,8 @@ public class Planet extends UnlockableContent{ public boolean prebuildBase = true; /** If true, waves are created on sector loss. TODO remove. */ public boolean allowWaves = false; + /** Icon as displayed in the planet selection dialog. This is a string, as drawables are null at load time. */ + public String icon = "commandRally"; /** Default core block for launching. */ public Block defaultCore = Blocks.coreShard; /** Sets up rules on game load for any sector on this planet. */ @@ -169,6 +173,10 @@ public class Planet extends UnlockableContent{ } } + public @Nullable Sector getStartSector(){ + return sectors.size == 0 ? null : sectors.get(startSector); + } + public void applyRules(Rules rules){ ruleSetter.get(rules); diff --git a/core/src/mindustry/ui/dialogs/PlanetDialog.java b/core/src/mindustry/ui/dialogs/PlanetDialog.java index 0f8a613e88..d1a5f4a4fa 100644 --- a/core/src/mindustry/ui/dialogs/PlanetDialog.java +++ b/core/src/mindustry/ui/dialogs/PlanetDialog.java @@ -1,8 +1,10 @@ package mindustry.ui.dialogs; import arc.*; +import arc.assets.loaders.TextureLoader.*; import arc.func.*; import arc.graphics.*; +import arc.graphics.Texture.*; import arc.graphics.g2d.*; import arc.graphics.gl.*; import arc.input.*; @@ -69,6 +71,8 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ public Table sectorTop = new Table(), notifs = new Table(), expandTable = new Table(); public Label hoverLabel = new Label(""); + private Texture[] planetTextures; + public PlanetDialog(){ super("", Styles.fullDialog); @@ -87,8 +91,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ //clear all except first, which is the last sector. newPresets.truncate(1); }else if(selected != null){ - selected = null; - updateSelected(); + selectSector(null); }else{ Core.app.post(() -> hide()); } @@ -160,6 +163,54 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ }); shown(this::setup); + + //show selection of Erekir/Serpulo campaign if the user has no bases, and hasn't selected yet (essentially a "have they played campaign before" check) + shown(() -> { + if(!settings.getBool("campaignselect") && !content.planets().contains(p -> p.sectors.contains(s -> s.hasBase()))){ + var diag = new BaseDialog("@campaign.select"); + + Planet[] selected = {null}; + var group = new ButtonGroup<>(); + group.setMinCheckCount(0); + state.planet = Planets.sun; + Planet[] choices = {Planets.serpulo, Planets.erekir}; + int i = 0; + for(var planet : choices){ + TextureRegion tex = new TextureRegion(planetTextures[i]); + + diag.cont.button(b -> { + b.top(); + b.add(planet.localizedName).color(Pal.accent).style(Styles.outlineLabel); + b.row(); + b.image(new TextureRegionDrawable(tex)).grow().scaling(Scaling.fit); + }, Styles.togglet, () -> selected[0] = planet).size(Core.app.isMobile() ? 220f : 320f).group(group); + i ++; + } + + diag.cont.row(); + diag.cont.label(() -> selected[0] == null ? "@campaign.none" : "@campaign." + selected[0].name).labelAlign(Align.center).style(Styles.outlineLabel).width(440f).wrap().colspan(2); + + diag.buttons.button("@ok", Icon.ok, () -> { + state.planet = selected[0]; + lookAt(state.planet.getStartSector()); + selectSector(state.planet.getStartSector()); + settings.put("campaignselect", true); + diag.hide(); + }).size(300f, 64f).disabled(b -> selected[0] == null); + + app.post(() -> diag.show()); + } + }); + + planetTextures = new Texture[2]; + String[] names = {"sprites/planets/serpulo.png", "sprites/planets/erekir.png"}; + for(int i = 0; i < names.length; i++){ + int fi = i; + assets.load(names[i], Texture.class, new TextureParameter(){{ + minFilter = magFilter = TextureFilter.linear; + }}).loaded = t -> planetTextures[fi] = t; + assets.finishLoadingAsset(names[i]); + } } /** show with no limitations, just as a map. */ @@ -551,17 +602,14 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ buttons, //planet selection new Table(t -> { - t.right(); + t.top().left(); if(content.planets().count(this::selectable) > 1){ - t.table(Styles.black6, pt -> { - pt.add("@planets").color(Pal.accent); - pt.row(); - pt.image().growX().height(4f).pad(6f).color(Pal.accent); - pt.row(); + t.table(Tex.pane, pt -> { + pt.margin(4f); for(int i = 0; i < content.planets().size; i++){ Planet planet = content.planets().get(i); if(selectable(planet)){ - pt.button(planet.localizedName, Styles.flatTogglet, () -> { + pt.button(planet.localizedName, Icon.icons.get(planet.icon + "Small", Icon.icons.get(planet.icon, Icon.commandRallySmall)), Styles.flatTogglet, () -> { selected = null; launchSector = null; if(state.planet != planet){ @@ -570,7 +618,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ rebuildExpand(); } settings.put("lastplanet", planet.name); - }).width(200).height(40).growX().update(bb -> bb.setChecked(state.planet == planet)); + }).width(190).height(40).growX().update(bb -> bb.setChecked(state.planet == planet)).with(w -> w.marginLeft(10f)).get().getChildren().get(1).setColor(planet.iconColor); pt.row(); } } @@ -943,6 +991,11 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ } } + void selectSector(Sector sector){ + selected = sector; + updateSelected(); + } + void updateSelected(){ Sector sector = selected; Table stable = sectorTop; @@ -1128,8 +1181,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ dialog.buttons.button("@sector.view", Icon.eyeSmall, () -> { dialog.hide(); lookAt(attacked); - selected = attacked; - updateSelected(); + selectSector(attacked); }); dialog.show();