diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index eea3c1046d..c1b8403293 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -1336,6 +1336,7 @@ rules.schematic = Schematics Allowed rules.wavetimer = Wave Timer rules.wavesending = Wave Sending rules.waves = Waves +rules.airUseSpawns = Air units use spawn points rules.attack = Attack Mode rules.buildai = Base Builder AI rules.buildaitier = Builder AI Tier diff --git a/core/assets/contributors b/core/assets/contributors index 8d2eb038ad..676853d30d 100644 --- a/core/assets/contributors +++ b/core/assets/contributors @@ -166,3 +166,4 @@ BalaM314 Redstonneur1256 ApsZoldat hexagon-recursion +JasonP01 diff --git a/core/src/mindustry/ai/WaveSpawner.java b/core/src/mindustry/ai/WaveSpawner.java index 1fd4b73521..e23dbbff5e 100644 --- a/core/src/mindustry/ai/WaveSpawner.java +++ b/core/src/mindustry/ai/WaveSpawner.java @@ -152,14 +152,21 @@ public class WaveSpawner{ } private void eachFlyerSpawn(int filterPos, Floatc2 cons){ + boolean airUseSpawns = state.rules.airUseSpawns; + for(Tile tile : spawns){ if(filterPos != -1 && filterPos != tile.pos()) continue; - float angle = Angles.angle(world.width() / 2f, world.height() / 2f, tile.x, tile.y); - float trns = Math.max(world.width(), world.height()) * Mathf.sqrt2 * tilesize; - float spawnX = Mathf.clamp(world.width() * tilesize / 2f + Angles.trnsx(angle, trns), -margin, world.width() * tilesize + margin); - float spawnY = Mathf.clamp(world.height() * tilesize / 2f + Angles.trnsy(angle, trns), -margin, world.height() * tilesize + margin); - cons.get(spawnX, spawnY); + if(!airUseSpawns){ + + float angle = Angles.angle(world.width() / 2f, world.height() / 2f, tile.x, tile.y); + float trns = Math.max(world.width(), world.height()) * Mathf.sqrt2 * tilesize; + float spawnX = Mathf.clamp(world.width() * tilesize / 2f + Angles.trnsx(angle, trns), -margin, world.width() * tilesize + margin); + float spawnY = Mathf.clamp(world.height() * tilesize / 2f + Angles.trnsy(angle, trns), -margin, world.height() * tilesize + margin); + cons.get(spawnX, spawnY); + }else{ + cons.get(tile.worldx(), tile.worldy()); + } } if(state.rules.attackMode && state.teams.isActive(state.rules.waveTeam)){ diff --git a/core/src/mindustry/game/Rules.java b/core/src/mindustry/game/Rules.java index 9da173c2df..5b2e44078f 100644 --- a/core/src/mindustry/game/Rules.java +++ b/core/src/mindustry/game/Rules.java @@ -29,6 +29,8 @@ public class Rules{ public boolean waveSending = true; /** Whether waves are spawnable at all. */ public boolean waves; + /** Whether air units spawn at spawns instead of the edge of the map */ + public boolean airUseSpawns = false; /** Whether the game objective is PvP. Note that this enables automatic hosting. */ public boolean pvp; /** Whether is waiting for players enabled in PvP. */ diff --git a/core/src/mindustry/ui/dialogs/CustomRulesDialog.java b/core/src/mindustry/ui/dialogs/CustomRulesDialog.java index 191da9852e..56d22c553d 100644 --- a/core/src/mindustry/ui/dialogs/CustomRulesDialog.java +++ b/core/src/mindustry/ui/dialogs/CustomRulesDialog.java @@ -215,6 +215,7 @@ public class CustomRulesDialog extends BaseDialog{ check("@rules.wavesending", b -> rules.waveSending = b, () -> rules.waveSending, () -> rules.waves); check("@rules.wavetimer", b -> rules.waveTimer = b, () -> rules.waveTimer, () -> rules.waves); check("@rules.waitForWaveToEnd", b -> rules.waitEnemies = b, () -> rules.waitEnemies, () -> rules.waves && rules.waveTimer); + check("@rules.airUseSpawns", b -> rules.airUseSpawns = b, () -> rules.airUseSpawns, () -> rules.waves); numberi("@rules.wavelimit", f -> rules.winWave = f, () -> rules.winWave, () -> rules.waves, 0, Integer.MAX_VALUE); number("@rules.wavespacing", false, f -> rules.waveSpacing = f * 60f, () -> rules.waveSpacing / 60f, () -> rules.waves && rules.waveTimer, 1, Float.MAX_VALUE); //this is experimental, because it's not clear that 0 makes it default.