From 4e225f91909b87f29c3ae67b3c5e9d5e8f677a29 Mon Sep 17 00:00:00 2001 From: Anuken Date: Mon, 3 Feb 2025 19:27:08 -0500 Subject: [PATCH] Internal support for legacy launch pads (hidden) --- core/assets/bundles/bundle.properties | 3 ++ core/src/mindustry/content/Blocks.java | 10 ++--- core/src/mindustry/content/Planets.java | 1 + core/src/mindustry/game/CampaignRules.java | 1 + core/src/mindustry/game/SectorInfo.java | 3 ++ core/src/mindustry/game/Universe.java | 43 ++++++++++++++++--- core/src/mindustry/type/Planet.java | 2 + .../ui/dialogs/CampaignRulesDialog.java | 5 +++ .../world/blocks/campaign/LandingPad.java | 11 +++-- .../world/blocks/campaign/LaunchPad.java | 4 +- .../mindustry/world/meta/BuildVisibility.java | 2 + 11 files changed, 69 insertions(+), 16 deletions(-) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index a5e15cc7e3..6bd6affbf8 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -1432,6 +1432,9 @@ rules.title.planet = Planet rules.lighting = Lighting rules.fog = Fog of War rules.invasions = Enemy Sector Invasions +rules.legacylaunchpads = Legacy Launch Pad Mechanics +rules.legacylaunchpads.info = Allows using launch pads without landing pads, as in 7.0. +landingpad.legacy.disabled = [scarlet]\ue815 Disabled[lightgray] (Legacy Launch Pads enabled) rules.showspawns = Show Enemy Spawns rules.randomwaveai = Unpredictable Wave AI rules.fire = Fire diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index fc95d69164..a3029ec77b 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -6354,7 +6354,7 @@ public class Blocks{ //region campaign launchPad = new LaunchPad("launch-pad"){{ - requirements(Category.effect, BuildVisibility.debugOnly, with(Items.copper, 350, Items.silicon, 140, Items.lead, 200, Items.titanium, 150)); + requirements(Category.effect, BuildVisibility.legacyLaunchPadOnly, with(Items.copper, 350, Items.silicon, 140, Items.lead, 200, Items.titanium, 150)); size = 3; itemCapacity = 100; launchTime = 60f * 20; @@ -6364,7 +6364,7 @@ public class Blocks{ }}; advancedLaunchPad = new LaunchPad("advanced-launch-pad"){{ - requirements(Category.effect, BuildVisibility.campaignOnly, with(Items.copper, 350, Items.silicon, 250, Items.lead, 300, Items.titanium, 200)); + requirements(Category.effect, BuildVisibility.notLegacyLaunchPadOnly, with(Items.copper, 350, Items.silicon, 250, Items.lead, 300, Items.titanium, 200)); size = 4; itemCapacity = 100; launchTime = 60f * 30; @@ -6376,14 +6376,14 @@ public class Blocks{ }}; landingPad = new LandingPad("landing-pad"){{ - requirements(Category.effect, BuildVisibility.campaignOnly, with(Items.copper, 200, Items.graphite, 100, Items.titanium, 100)); + requirements(Category.effect, BuildVisibility.notLegacyLaunchPadOnly, with(Items.copper, 200, Items.graphite, 100, Items.titanium, 100)); size = 4; itemCapacity = 100; coolingEffect = new RadialEffect(Fx.steamCoolSmoke, 4, 90f, 9.5f, 180f); - liquidCapacity = 4000f; - consumeLiquidAmount = 2000f; + liquidCapacity = 3000f; + consumeLiquidAmount = 1500f; }}; interplanetaryAccelerator = new Accelerator("interplanetary-accelerator"){{ diff --git a/core/src/mindustry/content/Planets.java b/core/src/mindustry/content/Planets.java index d23ab25f47..f44c617291 100644 --- a/core/src/mindustry/content/Planets.java +++ b/core/src/mindustry/content/Planets.java @@ -134,6 +134,7 @@ public class Planets{ launchCapacityMultiplier = 0.5f; sectorSeed = 2; allowWaves = true; + allowLegacyLaunchPads = true; allowWaveSimulation = true; allowSectorInvasion = true; allowLaunchSchematics = true; diff --git a/core/src/mindustry/game/CampaignRules.java b/core/src/mindustry/game/CampaignRules.java index 7ed813cab7..0ff9a7122c 100644 --- a/core/src/mindustry/game/CampaignRules.java +++ b/core/src/mindustry/game/CampaignRules.java @@ -8,6 +8,7 @@ public class CampaignRules{ public boolean showSpawns; public boolean sectorInvasion; public boolean randomWaveAI; + public boolean legacyLaunchPads; public void apply(Planet planet, Rules rules){ rules.staticFog = rules.fog = fog; diff --git a/core/src/mindustry/game/SectorInfo.java b/core/src/mindustry/game/SectorInfo.java index d7a3bf367d..0d8e8e1f06 100644 --- a/core/src/mindustry/game/SectorInfo.java +++ b/core/src/mindustry/game/SectorInfo.java @@ -92,6 +92,9 @@ public class SectorInfo{ public ObjectFloatMap importCooldownTimers = new ObjectFloatMap<>(); public @Nullable transient float[] importRateCache; + /** Temporary seq for last imported items. Do not use. */ + public transient ItemSeq lastImported = new ItemSeq(); + /** Counter refresh state. */ private transient Interval time = new Interval(); /** Core item storage input/output deltas. */ diff --git a/core/src/mindustry/game/Universe.java b/core/src/mindustry/game/Universe.java index 94945eae55..33fcc893c1 100644 --- a/core/src/mindustry/game/Universe.java +++ b/core/src/mindustry/game/Universe.java @@ -168,6 +168,33 @@ public class Universe{ continue; } + if(planet.campaignRules.legacyLaunchPads){ + //first pass: clear import stats + for(Sector sector : planet.sectors){ + if(sector.hasBase() && !sector.isBeingPlayed()){ + sector.info.lastImported.clear(); + } + } + + //second pass: update export & import statistics + for(Sector sector : planet.sectors){ + if(sector.hasBase() && !sector.isBeingPlayed()){ + + //export to another sector + if(sector.info.destination != null){ + Sector to = sector.info.destination; + if(to.hasBase() && to.planet == planet){ + ItemSeq items = new ItemSeq(); + //calculated exported items to this sector + sector.info.export.each((item, stat) -> items.add(item, (int)(stat.mean * newSecondsPassed * sector.getProductionScale()))); + to.addItems(items); + to.info.lastImported.add(items); + } + } + } + } + } + //third pass: everything else for(Sector sector : planet.sectors){ if(sector.hasBase()){ @@ -229,13 +256,15 @@ public class Universe{ //add production, making sure that it's capped sector.info.production.each((item, stat) -> sector.info.items.add(item, Math.min((int)(stat.mean * newSecondsPassed * scl), sector.info.storageCapacity - sector.info.items.get(item)))); - sector.info.export.each((item, stat) -> { - if(sector.info.items.get(item) <= 0 && sector.info.production.get(item, ExportStat::new).mean < 0 && stat.mean > 0){ - //cap export by import when production is negative. - //TODO remove - stat.mean = Math.min(0f, stat.mean); - } - }); + if(planet.campaignRules.legacyLaunchPads){ + sector.info.export.each((item, stat) -> { + if(sector.info.items.get(item) <= 0 && sector.info.production.get(item, ExportStat::new).mean < 0 && stat.mean > 0){ + //cap export by import when production is negative. + //TODO remove + stat.mean = Math.min(sector.info.lastImported.get(item) / (float)newSecondsPassed, stat.mean); + } + }); + } //prevent negative values with unloaders sector.info.items.checkNegative(); diff --git a/core/src/mindustry/type/Planet.java b/core/src/mindustry/type/Planet.java index 7ef88ed9e4..abf3897168 100644 --- a/core/src/mindustry/type/Planet.java +++ b/core/src/mindustry/type/Planet.java @@ -116,6 +116,8 @@ public class Planet extends UnlockableContent{ public boolean allowWaveSimulation = false; /** Whether to simulate sector invasions from enemy bases. */ public boolean allowSectorInvasion = false; + /** If true, legacy launch pads can be enabled. */ + public boolean allowLegacyLaunchPads = false; /** If true, sectors saves are cleared when lost. */ public boolean clearSectorOnLose = false; /** Multiplier for enemy rebuild speeds; only applied in campaign (not standard rules) */ diff --git a/core/src/mindustry/ui/dialogs/CampaignRulesDialog.java b/core/src/mindustry/ui/dialogs/CampaignRulesDialog.java index 55e6fda0e7..cebe4c72b3 100644 --- a/core/src/mindustry/ui/dialogs/CampaignRulesDialog.java +++ b/core/src/mindustry/ui/dialogs/CampaignRulesDialog.java @@ -68,6 +68,11 @@ public class CampaignRulesDialog extends BaseDialog{ check("@rules.fog", b -> rules.fog = b, () -> rules.fog); check("@rules.showspawns", b -> rules.showSpawns = b, () -> rules.showSpawns); check("@rules.randomwaveai", b -> rules.randomWaveAI = b, () -> rules.randomWaveAI); + + //TODO: this is intentionally hidden until the new mechanics have been well-tested. I don't want people immediately switching to the old mechanics + if(planet.allowLegacyLaunchPads){ + // check("@rules.legacylaunchpads", b -> rules.legacyLaunchPads = b, () -> rules.legacyLaunchPads); + } }).growY(); } diff --git a/core/src/mindustry/world/blocks/campaign/LandingPad.java b/core/src/mindustry/world/blocks/campaign/LandingPad.java index ab8a621352..d8b491d345 100644 --- a/core/src/mindustry/world/blocks/campaign/LandingPad.java +++ b/core/src/mindustry/world/blocks/campaign/LandingPad.java @@ -292,7 +292,7 @@ public class LandingPad extends Block{ cooldown = Mathf.clamp(cooldown); } - if(config != null && state.isCampaign()){ + if(config != null && state.isCampaign() && !state.getPlanet().campaignRules.legacyLaunchPads){ if(cooldown <= 0f && efficiency > 0f && items.total() == 0 && state.rules.sector.info.getImportRate(state.getPlanet(), config) > 0f && state.rules.sector.info.importCooldownTimers.get(config, 0f) >= 1f){ @@ -344,9 +344,14 @@ public class LandingPad extends Block{ table.row(); table.label(() -> { - if(config == null || !state.isCampaign()){ - return ""; + if(!state.isCampaign()) return ""; + + if(state.getPlanet().campaignRules.legacyLaunchPads){ + return Core.bundle.get("landingpad.legacy.disabled"); } + + if(config == null) return ""; + int sources = 0; float perSecond = 0f; for(var s : state.getPlanet().sectors){ diff --git a/core/src/mindustry/world/blocks/campaign/LaunchPad.java b/core/src/mindustry/world/blocks/campaign/LaunchPad.java index cb2014ee98..80fb16c353 100644 --- a/core/src/mindustry/world/blocks/campaign/LaunchPad.java +++ b/core/src/mindustry/world/blocks/campaign/LaunchPad.java @@ -296,7 +296,9 @@ public class LaunchPad extends Block{ Events.fire(new LaunchItemEvent(stack)); } - destsec.addItems(dest); + if(state.getPlanet().campaignRules.legacyLaunchPads){ + destsec.addItems(dest); + } } } } diff --git a/core/src/mindustry/world/meta/BuildVisibility.java b/core/src/mindustry/world/meta/BuildVisibility.java index 5572b3cdf2..06d08323f2 100644 --- a/core/src/mindustry/world/meta/BuildVisibility.java +++ b/core/src/mindustry/world/meta/BuildVisibility.java @@ -15,6 +15,8 @@ public class BuildVisibility{ worldProcessorOnly = new BuildVisibility(() -> Vars.state.rules.editor || Vars.state.rules.allowEditWorldProcessors), sandboxOnly = new BuildVisibility(() -> Vars.state == null || Vars.state.rules.infiniteResources), campaignOnly = new BuildVisibility(() -> Vars.state == null || Vars.state.isCampaign()), + legacyLaunchPadOnly = new BuildVisibility(() -> (Vars.state == null || Vars.state.isCampaign() && Vars.state.getPlanet().campaignRules.legacyLaunchPads) && Blocks.advancedLaunchPad != null && Blocks.advancedLaunchPad.unlocked()), + notLegacyLaunchPadOnly = new BuildVisibility(() -> (Vars.state == null || Vars.state.isCampaign() && !Vars.state.getPlanet().campaignRules.legacyLaunchPads)), lightingOnly = new BuildVisibility(() -> Vars.state == null || Vars.state.rules.lighting || Vars.state.isCampaign()), ammoOnly = new BuildVisibility(() -> Vars.state == null || Vars.state.rules.unitAmmo), fogOnly = new BuildVisibility(() -> Vars.state == null || Vars.state.rules.fog || Vars.state.rules.editor);