diff --git a/core/assets-raw/sprites/units/conquer.aseprite b/core/assets-raw/sprites/units/conquer.aseprite new file mode 100644 index 0000000000..4387c51df7 Binary files /dev/null and b/core/assets-raw/sprites/units/conquer.aseprite differ diff --git a/core/assets-raw/sprites/units/conquer.png b/core/assets-raw/sprites/units/conquer.png new file mode 100644 index 0000000000..08e6169584 Binary files /dev/null and b/core/assets-raw/sprites/units/conquer.png differ diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index d0daac7835..644e336282 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -616,6 +616,7 @@ sectors.rename = Rename Sector sectors.enemybase = [scarlet]Enemy Base sectors.vulnerable = [scarlet]Vulnerable sectors.underattack = [scarlet]Under attack! [accent]{0}% damaged +sectors.underattack.nodamage = [scarlet]Under attack! sectors.survives = [accent]Survives {0} waves sectors.go = Go sector.curcapture = Sector Captured @@ -626,6 +627,9 @@ sector.lost = Sector [accent]{0}[white] lost! #note: the missing space in the line below is intentional sector.captured = Sector [accent]{0}[white]captured! sector.changeicon = Change Icon +sector.noswitch.title = Unable to Switch Sectors +sector.noswitch = You may not switch sectors while an existing sector is under attack.\n\nSector: [accent]{0}[] on [accent]{1}[] +sector.view = View Sector threat.low = Low threat.medium = Medium @@ -1590,8 +1594,8 @@ block.core-foundation.description = Core of the base. Well armored. Stores more block.core-foundation.details = The second iteration. block.core-nucleus.description = Core of the base. Extremely well armored. Stores massive amounts of resources. block.core-nucleus.details = The third and final iteration. -block.vault.description = Stores a large amount of items of each type. Contents can be retrieved with an unloader. -block.container.description = Stores a small amount of items of each type. Contents can be retrieved with an unloader. +block.vault.description = Stores a large amount of items of each type. Expands storage when placed next to a core. Contents can be retrieved with an unloader. +block.container.description = Stores a small amount of items of each type. Expands storage when placed next to a core. Contents can be retrieved with an unloader. block.unloader.description = Unloads the selected item from nearby blocks. block.launch-pad.description = Launches batches of items to selected sectors. block.launch-pad.details = Sub-orbital system for point-to-point transportation of resources. Payload pods are fragile and incapable of surviving re-entry. diff --git a/core/src/mindustry/content/Planets.java b/core/src/mindustry/content/Planets.java index 0324fd80be..42fe36b87d 100644 --- a/core/src/mindustry/content/Planets.java +++ b/core/src/mindustry/content/Planets.java @@ -100,6 +100,8 @@ public class Planets{ new HexSkyMesh(this, 1, 0.6f, 0.16f, 5, Color.white.cpy().lerp(Pal.spore, 0.55f).a(0.75f), 2, 0.45f, 1f, 0.41f) ); + allowWaveSimulation = true; + allowSectorInvasion = true; allowLaunchSchematics = true; atmosphereColor = Color.valueOf("3c1b8f"); atmosphereRadIn = 0.02f; diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index f21de9f30e..99befc6099 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -2435,7 +2435,7 @@ public class UnitTypes{ speed = 0.6f; health = 9000; armor = 20f; - areaDamage = 10f; + areaDamage = 12f; treadRect = new Rect(22f, 16f, 28f, 130f); weapons.add(new Weapon("vanquish-weapon"){{ diff --git a/core/src/mindustry/core/Logic.java b/core/src/mindustry/core/Logic.java index 2da3ea9b4b..bf77ed5fc7 100644 --- a/core/src/mindustry/core/Logic.java +++ b/core/src/mindustry/core/Logic.java @@ -64,25 +64,28 @@ public class Logic implements ApplicationListener{ SectorInfo info = state.rules.sector.info; info.write(); - //how much wave time has passed - int wavesPassed = info.wavesPassed; + //only simulate waves if the planet allows it + if(state.rules.sector.planet.allowWaveSimulation){ + //how much wave time has passed + int wavesPassed = info.wavesPassed; - //wave has passed, remove all enemies, they are assumed to be dead - if(wavesPassed > 0){ - Groups.unit.each(u -> { - if(u.team == state.rules.waveTeam){ - u.remove(); - } - }); - } + //wave has passed, remove all enemies, they are assumed to be dead + if(wavesPassed > 0){ + Groups.unit.each(u -> { + if(u.team == state.rules.waveTeam){ + u.remove(); + } + }); + } - //simulate passing of waves - if(wavesPassed > 0){ - //simulate wave counter moving forward - state.wave += wavesPassed; - state.wavetime = state.rules.waveSpacing; + //simulate passing of waves + if(wavesPassed > 0){ + //simulate wave counter moving forward + state.wave += wavesPassed; + state.wavetime = state.rules.waveSpacing; - SectorDamage.applyCalculatedDamage(); + SectorDamage.applyCalculatedDamage(); + } } //reset values diff --git a/core/src/mindustry/game/SectorInfo.java b/core/src/mindustry/game/SectorInfo.java index 0900558353..c686d97b1a 100644 --- a/core/src/mindustry/game/SectorInfo.java +++ b/core/src/mindustry/game/SectorInfo.java @@ -204,7 +204,9 @@ public class SectorInfo{ state.rules.sector.saveInfo(); } - SectorDamage.writeParameters(this); + if(state.rules.sector != null && state.rules.sector.planet.allowWaveSimulation){ + SectorDamage.writeParameters(this); + } } /** Update averages of various stats, updates some special sector logic. diff --git a/core/src/mindustry/game/Universe.java b/core/src/mindustry/game/Universe.java index ec6124f861..39adf83536 100644 --- a/core/src/mindustry/game/Universe.java +++ b/core/src/mindustry/game/Universe.java @@ -194,7 +194,7 @@ public class Universe{ } int wavesPassed = (int)(sector.info.secondsPassed*60f / sector.info.waveSpacing); - boolean attacked = sector.info.waves; + boolean attacked = sector.info.waves && sector.planet.allowWaveSimulation; if(attacked){ sector.info.wavesPassed = wavesPassed; @@ -243,7 +243,7 @@ public class Universe{ } //queue random invasions - if(!sector.isAttacked() && sector.info.minutesCaptured > invasionGracePeriod && sector.info.hasSpawns){ + if(!sector.isAttacked() && sector.planet.allowSectorInvasion && sector.info.minutesCaptured > invasionGracePeriod && sector.info.hasSpawns){ int count = sector.near().count(Sector::hasEnemyBase); //invasion chance depends on # of nearby bases diff --git a/core/src/mindustry/type/Planet.java b/core/src/mindustry/type/Planet.java index ae2d8de0db..7864cca54e 100644 --- a/core/src/mindustry/type/Planet.java +++ b/core/src/mindustry/type/Planet.java @@ -90,6 +90,10 @@ public class Planet extends UnlockableContent{ public boolean hasAtmosphere = true; /** Whether to allow users to specify a custom launch schematic for this map. */ public boolean allowLaunchSchematics = false; + /** Whether to allow sectors to simulate waves in the background. */ + public boolean allowWaveSimulation = false; + /** Whether to simulate sector invasions from enemy bases. */ + public boolean allowSectorInvasion = false; /** Parent body that this planet orbits around. If null, this planet is considered to be in the middle of the solar system.*/ public @Nullable Planet parent; /** The root parent of the whole solar system this planet is in. */ diff --git a/core/src/mindustry/ui/dialogs/PlanetDialog.java b/core/src/mindustry/ui/dialogs/PlanetDialog.java index 7bbc93044f..52b2fc6382 100644 --- a/core/src/mindustry/ui/dialogs/PlanetDialog.java +++ b/core/src/mindustry/ui/dialogs/PlanetDialog.java @@ -412,13 +412,14 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ if(state.uiAlpha > 0.001f){ for(Sector sec : planet.sectors){ if(sec.hasBase()){ - for(Sector enemy : sec.near()){ - if(enemy.hasEnemyBase()){ - planets.drawArc(planet, enemy.tile.v, sec.tile.v, Team.crux.color.write(Tmp.c2).a(state.uiAlpha), Color.clear, 0.24f, 110f, 25); + if(planet.allowSectorInvasion){ + for(Sector enemy : sec.near()){ + if(enemy.hasEnemyBase()){ + planets.drawArc(planet, enemy.tile.v, sec.tile.v, Team.crux.color.write(Tmp.c2).a(state.uiAlpha), Color.clear, 0.24f, 110f, 25); + } } } - if(selected != null && selected != sec && selected.hasBase()){ //imports if(sec.info.getRealDestination() == selected && sec.info.anyExports()){ @@ -889,10 +890,10 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ void addSurvivedInfo(Sector sector, Table table, boolean wrap){ if(!wrap){ - table.add(Core.bundle.format("sectors.underattack", (int)(sector.info.damage * 100))).wrapLabel(wrap).row(); + table.add(sector.planet.allowWaveSimulation ? Core.bundle.format("sectors.underattack", (int)(sector.info.damage * 100)) : "@sectors.underattack.nodamage").wrapLabel(wrap).row(); } - if(sector.info.wavesSurvived >= 0 && sector.info.wavesSurvived - sector.info.wavesPassed >= 0 && !sector.isBeingPlayed()){ + if(sector.planet.allowWaveSimulation && sector.info.wavesSurvived >= 0 && sector.info.wavesSurvived - sector.info.wavesPassed >= 0 && !sector.isBeingPlayed()){ int toCapture = sector.info.attack || sector.info.winWave <= 1 ? -1 : sector.info.winWave - (sector.info.wave + sector.info.wavesPassed); boolean plus = (sector.info.wavesSurvived - sector.info.wavesPassed) >= SectorDamage.maxRetWave - 1; table.add(Core.bundle.format("sectors.survives", Math.min(sector.info.wavesSurvived - sector.info.wavesPassed, toCapture <= 0 ? 200 : toCapture) + @@ -1019,7 +1020,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ if(sector.isAttacked()){ addSurvivedInfo(sector, stable, false); - }else if(sector.hasBase() && sector.near().contains(Sector::hasEnemyBase)){ + }else if(sector.hasBase() && sector.planet.allowSectorInvasion && sector.near().contains(Sector::hasEnemyBase)){ stable.add("@sectors.vulnerable"); stable.row(); }else if(!sector.hasBase() && sector.hasEnemyBase()){ @@ -1073,6 +1074,33 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ return; } + //make sure there are no under-attack sectors (other than this one) + //TODO abandon button? + for(Planet planet : content.planets()){ + if(!planet.allowWaveSimulation){ + int attackedCount = planet.sectors.count(s -> s.isAttacked() && s != sector); + + //if there are two or more attacked sectors... something went wrong, don't show the dialog to prevent softlock + if(attackedCount < 2){ + Sector attacked = planet.sectors.find(s -> s.isAttacked() && s != sector); + if(attacked != null){ + BaseDialog dialog = new BaseDialog("@sector.noswitch.title"); + dialog.cont.add(bundle.format("sector.noswitch", attacked.name(), attacked.planet.localizedName)).maxWidth(400f).labelAlign(Align.center).center().wrap(); + dialog.addCloseButton(); + dialog.buttons.button("@sector.view", Icon.eyeSmall, () -> { + dialog.hide(); + lookAt(attacked); + selected = attacked; + updateSelected(); + }); + dialog.show(); + + return; + } + } + } + } + boolean shouldHide = true; //save before launch.