From ca823be813a719ad776a1eb7deccf50257bb99f7 Mon Sep 17 00:00:00 2001 From: way-zer Date: Sat, 29 Aug 2020 20:31:35 +0800 Subject: [PATCH 01/41] Update servers_be.json one bleeding-edge server of China --- servers_be.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/servers_be.json b/servers_be.json index 5c007872e5..3e420ee2eb 100644 --- a/servers_be.json +++ b/servers_be.json @@ -10,5 +10,8 @@ }, { "address": "routerchain.ddns.net" + }, + { + "address": "be.wayzer.cf" } ] From 55ed739372edcf16c7312808592ec9838c2104fe Mon Sep 17 00:00:00 2001 From: Recessive <61154659+Recessive@users.noreply.github.com> Date: Wed, 9 Sep 2020 14:27:26 +1000 Subject: [PATCH 02/41] Update servers.json Add {AA} Plague to the server listing --- servers.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/servers.json b/servers.json index 07226a273f..34241b026b 100644 --- a/servers.json +++ b/servers.json @@ -44,6 +44,9 @@ { "address": "aamindustry.play.ai:6568" }, + { + "address": "aamindustry.play.ai:6569" + }, { "address": "mindustry.atannergaming.com" }, From f30a3392d5830604dc09a21e3f126c46ef9d7979 Mon Sep 17 00:00:00 2001 From: Leonid Skorospelov Date: Sat, 3 Oct 2020 19:54:25 +0300 Subject: [PATCH 03/41] Update servers.json --- servers.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/servers.json b/servers.json index 8bb2e2097c..f13878499e 100644 --- a/servers.json +++ b/servers.json @@ -70,5 +70,8 @@ }, { "address": "pandorum.su:9999" + }, + { + "address": "mindustryranked.ddns.net" } ] From 5ffff9c151b522c374e0992f7719ff7dc6ca6bb7 Mon Sep 17 00:00:00 2001 From: summetdev Date: Sat, 3 Oct 2020 22:43:52 +0300 Subject: [PATCH 04/41] description for schematics --- core/src/mindustry/game/Schematic.java | 6 ++- core/src/mindustry/input/InputHandler.java | 34 ++++++++++++++- .../ui/dialogs/SchematicsDialog.java | 41 ++++++++++++++----- 3 files changed, 67 insertions(+), 14 deletions(-) diff --git a/core/src/mindustry/game/Schematic.java b/core/src/mindustry/game/Schematic.java index 5ad51382f2..9eaf0d99fe 100644 --- a/core/src/mindustry/game/Schematic.java +++ b/core/src/mindustry/game/Schematic.java @@ -62,6 +62,10 @@ public class Schematic implements Publishable, Comparable{ return tags.get("name", "unknown"); } + public String description(){ + return tags.get("description", ""); + } + public void save(){ schematics.saveChanges(this); } @@ -90,7 +94,7 @@ public class Schematic implements Publishable, Comparable{ @Override public String steamDescription(){ - return null; + return description(); } @Override diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java index 9034bcdd07..e27a3f15b2 100644 --- a/core/src/mindustry/input/InputHandler.java +++ b/core/src/mindustry/input/InputHandler.java @@ -10,6 +10,7 @@ import arc.math.*; import arc.math.geom.*; import arc.scene.*; import arc.scene.event.*; +import arc.scene.ui.*; import arc.scene.ui.layout.*; import arc.struct.*; import arc.util.ArcAnnotate.*; @@ -489,7 +490,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ protected void showSchematicSave(){ if(lastSchematic == null) return; - ui.showTextInput("@schematic.add", "@name", "", text -> { + Cons2 saveSchematic = (text, description) -> { Schematic replacement = schematics.all().find(s -> s.name().equals(text)); if(replacement != null){ ui.showConfirm("@confirm", "@schematic.replace", () -> { @@ -499,11 +500,40 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ }); }else{ lastSchematic.tags.put("name", text); + lastSchematic.tags.put("description", description); schematics.add(lastSchematic); ui.showInfoFade("@schematic.saved"); ui.schematics.showInfo(lastSchematic); } - }); + }; + + new Dialog("@schematic.add"){{ + cont.margin(30).add("@name").padRight(6f); + TextField nameField = cont.field("", t -> {}).size(330f, 50f).addInputDialog().get(); + + cont.row(); + + cont.margin(30).add("@editor.description").padRight(6f); + TextField descripionField = cont.field("", t -> {}).size(330f, 50f).addInputDialog().get(); + + buttons.defaults().size(120, 54).pad(4); + buttons.button("@ok", () -> { + saveSchematic.get(nameField.getText(), descripionField.getText()); + hide(); + }).disabled(b -> nameField.getText().isEmpty()); + buttons.button("@cancel", this::hide); + + keyDown(KeyCode.enter, () -> { + String text = nameField.getText(); + if(!text.isEmpty()){ + saveSchematic.get(text, descripionField.getText()); + hide(); + } + }); + keyDown(KeyCode.escape, this::hide); + keyDown(KeyCode.back, this::hide); + show(); + }}; } public void rotateRequests(Seq requests, int direction){ diff --git a/core/src/mindustry/ui/dialogs/SchematicsDialog.java b/core/src/mindustry/ui/dialogs/SchematicsDialog.java index 7a2afbbd1e..929ab0653f 100644 --- a/core/src/mindustry/ui/dialogs/SchematicsDialog.java +++ b/core/src/mindustry/ui/dialogs/SchematicsDialog.java @@ -4,6 +4,7 @@ import arc.*; import arc.graphics.*; import arc.graphics.Texture.*; import arc.graphics.g2d.*; +import arc.input.*; import arc.math.*; import arc.scene.style.*; import arc.scene.ui.*; @@ -106,18 +107,36 @@ public class SchematicsDialog extends BaseDialog{ }); buttons.button(Icon.pencil, style, () -> { - ui.showTextInput("@schematic.rename", "@name", s.name(), res -> { - Schematic replacement = schematics.all().find(other -> other.name().equals(res) && other != s); - if(replacement != null){ - //renaming to an existing schematic is not allowed, as it is not clear how the tags would be merged, and which one should be removed - ui.showErrorMessage("@schematic.exists"); - return; - } + new Dialog("@schematic.rename"){{ + cont.margin(30).add("@name").padRight(6f); + TextField nameField = cont.field(s.name(), null).size(330f, 50f).addInputDialog().get(); - s.tags.put("name", res); - s.save(); - rebuildPane[0].run(); - }); + cont.row(); + + cont.margin(30).add("@editor.description").padRight(6f); + TextField descripionField = cont.field(s.description(), null).size(330f, 50f).addInputDialog().get(); + + Runnable accept = () -> { + s.tags.put("name", nameField.getText()); + s.tags.put("description", descripionField.getText()); + s.save(); + hide(); + rebuildPane[0].run(); + }; + + buttons.defaults().size(120, 54).pad(4); + buttons.button("@ok", accept).disabled(b -> nameField.getText().isEmpty()); + buttons.button("@cancel", this::hide); + + keyDown(KeyCode.enter, () -> { + if(!nameField.getText().isEmpty()){ + accept.run(); + } + }); + keyDown(KeyCode.escape, this::hide); + keyDown(KeyCode.back, this::hide); + show(); + }}; }); if(s.hasSteamID()){ From eedb90ed167fb449d771d8ac08c3274829bbf6dc Mon Sep 17 00:00:00 2001 From: summetdev Date: Sun, 4 Oct 2020 15:27:05 +0300 Subject: [PATCH 05/41] bigger description area --- core/src/mindustry/ui/dialogs/SchematicsDialog.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/mindustry/ui/dialogs/SchematicsDialog.java b/core/src/mindustry/ui/dialogs/SchematicsDialog.java index 929ab0653f..341ac3c85a 100644 --- a/core/src/mindustry/ui/dialogs/SchematicsDialog.java +++ b/core/src/mindustry/ui/dialogs/SchematicsDialog.java @@ -109,12 +109,12 @@ public class SchematicsDialog extends BaseDialog{ buttons.button(Icon.pencil, style, () -> { new Dialog("@schematic.rename"){{ cont.margin(30).add("@name").padRight(6f); - TextField nameField = cont.field(s.name(), null).size(330f, 50f).addInputDialog().get(); + TextField nameField = cont.field(s.name(), null).size(400f, 55f).addInputDialog().get(); cont.row(); cont.margin(30).add("@editor.description").padRight(6f); - TextField descripionField = cont.field(s.description(), null).size(330f, 50f).addInputDialog().get(); + TextField descripionField = cont.area(s.description(), Styles.areaField, t -> {}).size(400f, 140f).addInputDialog().get(); Runnable accept = () -> { s.tags.put("name", nameField.getText()); From bdc69249bbb763c6d4d35912319c7073629ac42d Mon Sep 17 00:00:00 2001 From: summetdev Date: Sun, 4 Oct 2020 16:03:48 +0300 Subject: [PATCH 06/41] fix newline --- core/src/mindustry/ui/dialogs/SchematicsDialog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/mindustry/ui/dialogs/SchematicsDialog.java b/core/src/mindustry/ui/dialogs/SchematicsDialog.java index 341ac3c85a..35055267e2 100644 --- a/core/src/mindustry/ui/dialogs/SchematicsDialog.java +++ b/core/src/mindustry/ui/dialogs/SchematicsDialog.java @@ -129,7 +129,7 @@ public class SchematicsDialog extends BaseDialog{ buttons.button("@cancel", this::hide); keyDown(KeyCode.enter, () -> { - if(!nameField.getText().isEmpty()){ + if(!nameField.getText().isEmpty() && Core.scene.getKeyboardFocus() != descripionField){ accept.run(); } }); From 3d4ace6ca856065ded2222c67a24b2bb9b73ae97 Mon Sep 17 00:00:00 2001 From: MEEP of Faith <54301439+MEEPofFaith@users.noreply.github.com> Date: Wed, 7 Oct 2020 18:24:30 -0700 Subject: [PATCH 07/41] If units can have `chargeSound`, why not `chargeTurret`s too? --- .../mindustry/world/blocks/defense/turrets/ChargeTurret.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/src/mindustry/world/blocks/defense/turrets/ChargeTurret.java b/core/src/mindustry/world/blocks/defense/turrets/ChargeTurret.java index 3680cce446..d5e7767cdf 100644 --- a/core/src/mindustry/world/blocks/defense/turrets/ChargeTurret.java +++ b/core/src/mindustry/world/blocks/defense/turrets/ChargeTurret.java @@ -1,5 +1,6 @@ package mindustry.world.blocks.defense.turrets; +import arc.audio.*; import arc.math.*; import arc.util.*; import mindustry.content.*; @@ -14,6 +15,7 @@ public class ChargeTurret extends PowerTurret{ public float chargeMaxDelay = 10f; public Effect chargeEffect = Fx.none; public Effect chargeBeginEffect = Fx.none; + public Sound chargeSound = Sounds.none; public ChargeTurret(String name){ super(name); @@ -28,7 +30,8 @@ public class ChargeTurret extends PowerTurret{ tr.trns(rotation, size * tilesize / 2f); chargeBeginEffect.at(x + tr.x, y + tr.y, rotation); - + chargeSound.at(tile, Mathf.random(0.9f, 1.1f)); + for(int i = 0; i < chargeEffects; i++){ Time.run(Mathf.random(chargeMaxDelay), () -> { if(!isValid()) return; From 4317cad110d4c8031c46e6a74a99a98fa6da87c5 Mon Sep 17 00:00:00 2001 From: MEEP of Faith Date: Wed, 7 Oct 2020 19:07:01 -0700 Subject: [PATCH 08/41] Since my Gradle is broken or something, I'll be relying on Travis until I get it fixed. --- .../mindustry/world/blocks/defense/turrets/ChargeTurret.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/src/mindustry/world/blocks/defense/turrets/ChargeTurret.java b/core/src/mindustry/world/blocks/defense/turrets/ChargeTurret.java index d5e7767cdf..ab0cfbd9e4 100644 --- a/core/src/mindustry/world/blocks/defense/turrets/ChargeTurret.java +++ b/core/src/mindustry/world/blocks/defense/turrets/ChargeTurret.java @@ -6,6 +6,7 @@ import arc.util.*; import mindustry.content.*; import mindustry.entities.*; import mindustry.entities.bullet.*; +import mindustry.type.*; import static mindustry.Vars.*; @@ -30,7 +31,7 @@ public class ChargeTurret extends PowerTurret{ tr.trns(rotation, size * tilesize / 2f); chargeBeginEffect.at(x + tr.x, y + tr.y, rotation); - chargeSound.at(tile, Mathf.random(0.9f, 1.1f)); + chargeSound.at(x + tr.x, y + tr.y, Mathf.random(0.8f, 1f)); for(int i = 0; i < chargeEffects; i++){ Time.run(Mathf.random(chargeMaxDelay), () -> { From f93b80dd3692df24c76cefa1139754df611b22ae Mon Sep 17 00:00:00 2001 From: MEEP of Faith Date: Wed, 7 Oct 2020 21:24:32 -0700 Subject: [PATCH 09/41] thx --- .../src/mindustry/world/blocks/defense/turrets/ChargeTurret.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/mindustry/world/blocks/defense/turrets/ChargeTurret.java b/core/src/mindustry/world/blocks/defense/turrets/ChargeTurret.java index ab0cfbd9e4..197ca83358 100644 --- a/core/src/mindustry/world/blocks/defense/turrets/ChargeTurret.java +++ b/core/src/mindustry/world/blocks/defense/turrets/ChargeTurret.java @@ -7,6 +7,7 @@ import mindustry.content.*; import mindustry.entities.*; import mindustry.entities.bullet.*; import mindustry.type.*; +import mindustry.gen.*; import static mindustry.Vars.*; From d94fdfa50f6cc94cd16b11211f6ede281641a62a Mon Sep 17 00:00:00 2001 From: summetdev Date: Sat, 10 Oct 2020 20:28:43 +0300 Subject: [PATCH 10/41] don't show desc at schem save --- core/src/mindustry/input/InputHandler.java | 34 ++-------------------- 1 file changed, 3 insertions(+), 31 deletions(-) diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java index e27a3f15b2..677fb4f35b 100644 --- a/core/src/mindustry/input/InputHandler.java +++ b/core/src/mindustry/input/InputHandler.java @@ -490,7 +490,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ protected void showSchematicSave(){ if(lastSchematic == null) return; - Cons2 saveSchematic = (text, description) -> { + ui.showTextInput("@schematic.add", "@name", "", text -> { Schematic replacement = schematics.all().find(s -> s.name().equals(text)); if(replacement != null){ ui.showConfirm("@confirm", "@schematic.replace", () -> { @@ -500,40 +500,12 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ }); }else{ lastSchematic.tags.put("name", text); - lastSchematic.tags.put("description", description); + lastSchematic.tags.put("description", ""); schematics.add(lastSchematic); ui.showInfoFade("@schematic.saved"); ui.schematics.showInfo(lastSchematic); } - }; - - new Dialog("@schematic.add"){{ - cont.margin(30).add("@name").padRight(6f); - TextField nameField = cont.field("", t -> {}).size(330f, 50f).addInputDialog().get(); - - cont.row(); - - cont.margin(30).add("@editor.description").padRight(6f); - TextField descripionField = cont.field("", t -> {}).size(330f, 50f).addInputDialog().get(); - - buttons.defaults().size(120, 54).pad(4); - buttons.button("@ok", () -> { - saveSchematic.get(nameField.getText(), descripionField.getText()); - hide(); - }).disabled(b -> nameField.getText().isEmpty()); - buttons.button("@cancel", this::hide); - - keyDown(KeyCode.enter, () -> { - String text = nameField.getText(); - if(!text.isEmpty()){ - saveSchematic.get(text, descripionField.getText()); - hide(); - } - }); - keyDown(KeyCode.escape, this::hide); - keyDown(KeyCode.back, this::hide); - show(); - }}; + }); } public void rotateRequests(Seq requests, int direction){ From c2202a017339e989f72854cc39a202c328f83be8 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 10 Oct 2020 15:50:03 -0400 Subject: [PATCH 11/41] Bugfixes --- core/src/mindustry/ai/types/SuicideAI.java | 53 +++++++++++-------- core/src/mindustry/content/UnitTypes.java | 18 +++---- core/src/mindustry/mod/ContentParser.java | 2 +- .../mindustry/world/blocks/defense/Wall.java | 2 +- 4 files changed, 42 insertions(+), 33 deletions(-) diff --git a/core/src/mindustry/ai/types/SuicideAI.java b/core/src/mindustry/ai/types/SuicideAI.java index 7278062605..789fb93f4b 100644 --- a/core/src/mindustry/ai/types/SuicideAI.java +++ b/core/src/mindustry/ai/types/SuicideAI.java @@ -6,6 +6,8 @@ import mindustry.entities.*; import mindustry.entities.units.*; import mindustry.gen.*; import mindustry.world.*; +import mindustry.world.blocks.distribution.*; +import mindustry.world.blocks.liquid.*; import mindustry.world.meta.*; public class SuicideAI extends GroundAI{ @@ -14,7 +16,7 @@ public class SuicideAI extends GroundAI{ @Override public void updateUnit(){ - if(Units.invalidateTarget(target, unit.team(), unit.x(), unit.y(), Float.MAX_VALUE)){ + if(Units.invalidateTarget(target, unit.team, unit.x, unit.y, Float.MAX_VALUE)){ target = null; } @@ -35,29 +37,32 @@ public class SuicideAI extends GroundAI{ unit.aimLook(Predict.intercept(unit, target, unit.type().weapons.first().bullet.speed)); } - blockedByBlock = false; + //do not move toward walls or transport blocks + if(!(target instanceof Building build && (build.block.group == BlockGroup.walls || build.block.group == BlockGroup.liquids || build.block.group == BlockGroup.transportation))){ + blockedByBlock = false; - //raycast for target - boolean blocked = Vars.world.raycast(unit.tileX(), unit.tileY(), target.tileX(), target.tileY(), (x, y) -> { - Tile tile = Vars.world.tile(x, y); - if(tile != null && tile.build == target) return false; - if(tile != null && tile.build != null && tile.build.team != unit.team()){ - blockedByBlock = true; - return true; - }else{ - return tile == null || tile.solid(); + //raycast for target + boolean blocked = Vars.world.raycast(unit.tileX(), unit.tileY(), target.tileX(), target.tileY(), (x, y) -> { + Tile tile = Vars.world.tile(x, y); + if(tile != null && tile.build == target) return false; + if(tile != null && tile.build != null && tile.build.team != unit.team()){ + blockedByBlock = true; + return true; + }else{ + return tile == null || tile.solid(); + } + }); + + //shoot when there's an enemy block in the way + if(blockedByBlock){ + shoot = true; } - }); - //shoot when there's an enemy block in the way - if(blockedByBlock){ - shoot = true; - } - - if(!blocked){ - moveToTarget = true; - //move towards target directly - unit.moveAt(vec.set(target).sub(unit).limit(unit.type().speed)); + if(!blocked){ + moveToTarget = true; + //move towards target directly + unit.moveAt(vec.set(target).sub(unit).limit(unit.type().speed)); + } } } @@ -78,4 +83,10 @@ public class SuicideAI extends GroundAI{ unit.controlWeapons(rotate, shoot); } + + @Override + protected Teamc target(float x, float y, float range, boolean air, boolean ground){ + return Units.closestTarget(unit.team, x, y, range, u -> u.checkTarget(air, ground), t -> ground && + !(t.block instanceof Conveyor || t.block instanceof Conduit)); //do not target conveyors/conduits + } } diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index d01be43902..17ec827055 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -514,7 +514,7 @@ public class UnitTypes implements ContentList{ crawler = new UnitType("crawler"){{ defaultController = SuicideAI::new; - speed = 0.92f; + speed = 1f; hitSize = 8f; health = 180; mechSideSway = 0.25f; @@ -529,9 +529,9 @@ public class UnitTypes implements ContentList{ hitEffect = Fx.pulverize; lifetime = 10f; speed = 1f; - splashDamageRadius = 55f; + splashDamageRadius = 70f; instantDisappear = true; - splashDamage = 60f; + splashDamage = 80f; killShooter = true; hittable = false; collidesAir = true; @@ -1187,8 +1187,6 @@ public class UnitTypes implements ContentList{ healPercent = 5.5f; collidesTeam = true; backColor = Pal.heal; - frontColor = Color.white; - backColor = Pal.heal; trailColor = Pal.heal; }}; }}); @@ -1233,7 +1231,7 @@ public class UnitTypes implements ContentList{ }}; quad = new UnitType("quad"){{ - armor = 4f; + armor = 6f; health = 6000; speed = 1.2f; rotateSpeed = 2f; @@ -1256,7 +1254,7 @@ public class UnitTypes implements ContentList{ new Weapon(){{ x = y = 0f; mirror = false; - reload = 60f; + reload = 55f; minShootVelocity = 0.01f; bullet = new BasicBulletType(){{ @@ -1289,9 +1287,9 @@ public class UnitTypes implements ContentList{ speed = 0.001f; collides = false; - healPercent = 10f; - splashDamage = 240f; - splashDamageRadius = 115f; + healPercent = 15f; + splashDamage = 320f; + splashDamageRadius = 120f; }}; }}); }}; diff --git a/core/src/mindustry/mod/ContentParser.java b/core/src/mindustry/mod/ContentParser.java index 38f4db6a82..b9c119ee32 100644 --- a/core/src/mindustry/mod/ContentParser.java +++ b/core/src/mindustry/mod/ContentParser.java @@ -603,7 +603,7 @@ public class ContentParser{ customRequirements = null; }else{ researchName = research.getString("parent"); - customRequirements = research.hasChild("requirements") ? parser.readValue(ItemStack[].class, research.getChild("requirements")) : null; + customRequirements = research.has("requirements") ? parser.readValue(ItemStack[].class, research.get("requirements")) : null; } //remove old node diff --git a/core/src/mindustry/world/blocks/defense/Wall.java b/core/src/mindustry/world/blocks/defense/Wall.java index 873cbaea78..abb941b899 100644 --- a/core/src/mindustry/world/blocks/defense/Wall.java +++ b/core/src/mindustry/world/blocks/defense/Wall.java @@ -34,7 +34,7 @@ public class Wall extends Block{ solid = true; destructible = true; group = BlockGroup.walls; - buildCostMultiplier = 5f; + buildCostMultiplier = 6f; canOverdrive = false; } From 4d889cd8d126c3e66f957ea43c82cd534873638d Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 10 Oct 2020 17:09:19 -0400 Subject: [PATCH 12/41] Weather fixes --- core/src/mindustry/content/UnitTypes.java | 2 +- core/src/mindustry/content/Weathers.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index 17ec827055..f98676f156 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -1231,7 +1231,7 @@ public class UnitTypes implements ContentList{ }}; quad = new UnitType("quad"){{ - armor = 6f; + armor = 8f; health = 6000; speed = 1.2f; rotateSpeed = 2f; diff --git a/core/src/mindustry/content/Weathers.java b/core/src/mindustry/content/Weathers.java index a2ffbb098f..273fdb5899 100644 --- a/core/src/mindustry/content/Weathers.java +++ b/core/src/mindustry/content/Weathers.java @@ -152,7 +152,7 @@ public class Weathers implements ContentList{ if(tile != null && tile.floor().liquidDrop == Liquids.water){ Draw.color(Tmp.c1.set(tile.floor().mapColor).mul(1.5f).a(state.opacity())); Draw.rect(splashes[(int)(life * (splashes.length - 1))], x, y); - }else{ + }else if(tile != null && tile.floor().liquidDrop == null && !tile.floor().solid){ Draw.color(Color.royal, Color.white, 0.3f); Draw.alpha(Mathf.slope(life) * state.opacity()); From ab772d4901ef59cf245edf08ef5fcd27d1ea6379 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 10 Oct 2020 17:31:16 -0400 Subject: [PATCH 13/41] fewer destruction turns --- core/src/mindustry/Vars.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/mindustry/Vars.java b/core/src/mindustry/Vars.java index e0871c74ac..be658a7a87 100644 --- a/core/src/mindustry/Vars.java +++ b/core/src/mindustry/Vars.java @@ -87,7 +87,7 @@ public class Vars implements Loadable{ /** duration of time between turns in ticks */ public static final float turnDuration = 20 * Time.toMinutes; /** turns needed to destroy a sector completely */ - public static final float sectorDestructionTurns = 3f; + public static final float sectorDestructionTurns = 2f; /** min armor fraction damage; e.g. 0.05 = at least 5% damage */ public static final float minArmorDamage = 0.1f; /** launch animation duration */ From bcb248907c8d7bb3fdce5574b4fe455c4084c0c8 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 10 Oct 2020 19:02:47 -0400 Subject: [PATCH 14/41] Campaign core item incineration + better idle gen --- .../mindustry/entities/comp/BuildingComp.java | 5 +++ core/src/mindustry/game/SectorInfo.java | 38 +++++++++---------- core/src/mindustry/game/Universe.java | 4 +- core/src/mindustry/type/Sector.java | 10 ++++- .../world/blocks/storage/CoreBlock.java | 28 +++++++++++++- .../world/blocks/storage/StorageBlock.java | 24 ++++++++++++ .../world/blocks/storage/Unloader.java | 1 + 7 files changed, 84 insertions(+), 26 deletions(-) diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index 4a8e23e6cf..3a6c0ea8f0 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -348,6 +348,11 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, //endregion //region handler methods + /** Called when an unloader takes an item. */ + public void itemTaken(Item item){ + + } + /** Called when this block is dropped as a payload. */ public void dropped(){ diff --git a/core/src/mindustry/game/SectorInfo.java b/core/src/mindustry/game/SectorInfo.java index dc56902c60..b66dc5bf95 100644 --- a/core/src/mindustry/game/SectorInfo.java +++ b/core/src/mindustry/game/SectorInfo.java @@ -10,6 +10,8 @@ import mindustry.world.*; import mindustry.world.blocks.storage.CoreBlock.*; import mindustry.world.modules.*; +import java.util.*; + import static mindustry.Vars.*; public class SectorInfo{ @@ -42,7 +44,15 @@ public class SectorInfo{ /** Counter refresh state. */ private transient Interval time = new Interval(); /** Core item storage to prevent spoofing. */ - private transient int[] lastCoreItems; + private transient int[] coreItemCounts; + + /** Handles core item changes. */ + public void handleCoreItem(Item item, int amount){ + if(coreItemCounts == null){ + coreItemCounts = new int[content.items().size]; + } + coreItemCounts[item.id] += amount; + } /** @return the real location items go when launched on this sector */ public Sector getRealDestination(){ @@ -105,12 +115,6 @@ public class SectorInfo{ universe.runTurn(); } - //create last stored core items - if(lastCoreItems == null){ - lastCoreItems = new int[content.items().size]; - updateCoreDeltas(); - } - CoreBuild ent = state.rules.defaultTeam.core(); //refresh throughput @@ -124,15 +128,16 @@ public class SectorInfo{ stat.loaded = true; } - //how the resources changed - only interested in negative deltas, since that's what happens during spoofing - int coreDelta = Math.min(ent == null ? 0 : ent.items.get(item) - lastCoreItems[item.id], 0); - //add counter, subtract how many items were taken from the core during this time - stat.means.add(Math.max(stat.counter + coreDelta, 0)); + stat.means.add(Math.max(stat.counter, 0)); stat.counter = 0; stat.mean = stat.means.rawMean(); }); + if(coreItemCounts == null){ + coreItemCounts = new int[content.items().size]; + } + //refresh core items for(Item item : content.items()){ ExportStat stat = production.get(item, ExportStat::new); @@ -143,21 +148,14 @@ public class SectorInfo{ //get item delta //TODO is preventing negative production a good idea? - int delta = Math.max((ent == null ? 0 : ent.items.get(item)) - lastCoreItems[item.id], 0); + int delta = Math.max(ent == null ? 0 : coreItemCounts[item.id], 0); //store means stat.means.add(delta); stat.mean = stat.means.rawMean(); } - updateCoreDeltas(); - } - } - - private void updateCoreDeltas(){ - CoreBuild ent = state.rules.defaultTeam.core(); - for(int i = 0; i < lastCoreItems.length; i++){ - lastCoreItems[i] = ent == null ? 0 : ent.items.get(i); + Arrays.fill(coreItemCounts, 0); } } diff --git a/core/src/mindustry/game/Universe.java b/core/src/mindustry/game/Universe.java index b2c9c7d039..e64b4cfc07 100644 --- a/core/src/mindustry/game/Universe.java +++ b/core/src/mindustry/game/Universe.java @@ -158,10 +158,10 @@ public class Universe{ if(sector.save != null && sector.save.meta != null && sector.save.meta.secinfo != null && sector.save.meta.secinfo.destination != null){ Sector to = sector.save.meta.secinfo.destination; if(to.save != null){ - ItemSeq items = to.getExtraItems(); + ItemSeq items = new ItemSeq(); //calculated exported items to this sector sector.save.meta.secinfo.export.each((item, stat) -> items.add(item, (int)(stat.mean * newSecondsPassed))); - to.setExtraItems(items); + to.addItems(items); } } diff --git a/core/src/mindustry/type/Sector.java b/core/src/mindustry/type/Sector.java index 6d042296d1..21152cc954 100644 --- a/core/src/mindustry/type/Sector.java +++ b/core/src/mindustry/type/Sector.java @@ -143,9 +143,15 @@ public class Sector{ } public void removeItem(Item item, int amount){ + ItemSeq seq = new ItemSeq(); + seq.add(item, -amount); + addItems(seq); + } + + public void addItems(ItemSeq items){ if(isBeingPlayed()){ if(state.rules.defaultTeam.core() != null){ - state.rules.defaultTeam.items().remove(item, amount); + state.rules.defaultTeam.items().add(items); } }else{ ItemSeq recv = getExtraItems(); @@ -170,7 +176,7 @@ public class Sector{ }); } - recv.remove(item, amount); + recv.add(items); setExtraItems(recv); } diff --git a/core/src/mindustry/world/blocks/storage/CoreBlock.java b/core/src/mindustry/world/blocks/storage/CoreBlock.java index 295a127f2b..14d60280ee 100644 --- a/core/src/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/mindustry/world/blocks/storage/CoreBlock.java @@ -157,6 +157,7 @@ public class CoreBlock extends StorageBlock{ public int storageCapacity; //note that this unit is never actually used for control; the possession handler makes the player respawn when this unit is controlled public BlockUnitc unit = Nulls.blockUnit; + public boolean noEffect = false; @Override public void created(){ @@ -195,7 +196,7 @@ public class CoreBlock extends StorageBlock{ @Override public boolean acceptItem(Building source, Item item){ - return items.get(item) < getMaximumAccepted(item); + return items.get(item) < getMaximumAccepted(item) || incinerate(); } @Override @@ -264,6 +265,10 @@ public class CoreBlock extends StorageBlock{ return tile instanceof StorageBuild && (((StorageBuild)tile).linkedCore == core || ((StorageBuild)tile).linkedCore == null); } + public boolean incinerate(){ + return state.isCampaign(); + } + @Override public float handleDamage(float amount){ if(player != null && team == player.team()){ @@ -298,16 +303,35 @@ public class CoreBlock extends StorageBlock{ } } + @Override public void placed(){ super.placed(); state.teams.registerCore(this); } + @Override + public void itemTaken(Item item){ + if(state.isCampaign()){ + //update item taken amount + state.secinfo.handleCoreItem(item, -1); + } + } + @Override public void handleItem(Building source, Item item){ if(net.server() || !net.active()){ - super.handleItem(source, item); + + if(items.get(item) >= getMaximumAccepted(item)){ + //create item incineration effect at random intervals + if(!noEffect){ + incinerateEffect(this, source); + } + noEffect = false; + }else{ + super.handleItem(source, item); + } + if(state.rules.tutorial){ Events.fire(new CoreItemDeliverEvent()); } diff --git a/core/src/mindustry/world/blocks/storage/StorageBlock.java b/core/src/mindustry/world/blocks/storage/StorageBlock.java index 320d70868a..50eb65a270 100644 --- a/core/src/mindustry/world/blocks/storage/StorageBlock.java +++ b/core/src/mindustry/world/blocks/storage/StorageBlock.java @@ -1,10 +1,13 @@ package mindustry.world.blocks.storage; +import arc.math.*; import arc.struct.*; import arc.util.*; +import mindustry.content.*; import mindustry.gen.*; import mindustry.type.*; import mindustry.world.*; +import mindustry.world.blocks.storage.CoreBlock.*; import mindustry.world.meta.*; public class StorageBlock extends Block{ @@ -22,6 +25,16 @@ public class StorageBlock extends Block{ return false; } + public static void incinerateEffect(Building self, Building source){ + if(Mathf.chance(0.1)){ + Tile edge = Edges.getFacingEdge(source, self); + Tile edge2 = Edges.getFacingEdge(self, source); + if(edge != null && edge2 != null){ + Fx.fuelburn.at((edge.worldx() + edge2.worldx())/2f, (edge.worldy() + edge2.worldy())/2f); + } + } + } + public class StorageBuild extends Building{ protected @Nullable Building linkedCore; @@ -30,6 +43,17 @@ public class StorageBlock extends Block{ return linkedCore != null ? linkedCore.acceptItem(source, item) : items.get(item) < getMaximumAccepted(item); } + @Override + public void handleItem(Building source, Item item){ + if(linkedCore != null){ + incinerateEffect(this, source); + ((CoreBuild)linkedCore).noEffect = true; + linkedCore.handleItem(source, item); + }else{ + super.handleItem(source, item); + } + } + @Override public int getMaximumAccepted(Item item){ return itemCapacity; diff --git a/core/src/mindustry/world/blocks/storage/Unloader.java b/core/src/mindustry/world/blocks/storage/Unloader.java index 86ce15956e..524d6eb939 100644 --- a/core/src/mindustry/world/blocks/storage/Unloader.java +++ b/core/src/mindustry/world/blocks/storage/Unloader.java @@ -66,6 +66,7 @@ public class Unloader extends Block{ }else{ other.items.remove(item, 1); } + other.itemTaken(item); } } } From 5600f96a37c6e87a55132281ebae20f83f3c9cb8 Mon Sep 17 00:00:00 2001 From: MEEP of Faith Date: Sat, 10 Oct 2020 18:03:53 -0700 Subject: [PATCH 15/41] Make the sound pitch not random. --- .../mindustry/world/blocks/defense/turrets/ChargeTurret.java | 2 +- core/src/mindustry/world/blocks/defense/turrets/Turret.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/mindustry/world/blocks/defense/turrets/ChargeTurret.java b/core/src/mindustry/world/blocks/defense/turrets/ChargeTurret.java index 197ca83358..15feaf0379 100644 --- a/core/src/mindustry/world/blocks/defense/turrets/ChargeTurret.java +++ b/core/src/mindustry/world/blocks/defense/turrets/ChargeTurret.java @@ -32,7 +32,7 @@ public class ChargeTurret extends PowerTurret{ tr.trns(rotation, size * tilesize / 2f); chargeBeginEffect.at(x + tr.x, y + tr.y, rotation); - chargeSound.at(x + tr.x, y + tr.y, Mathf.random(0.8f, 1f)); + chargeSound.at(x + tr.x, y + tr.y, 1); for(int i = 0; i < chargeEffects; i++){ Time.run(Mathf.random(chargeMaxDelay), () -> { diff --git a/core/src/mindustry/world/blocks/defense/turrets/Turret.java b/core/src/mindustry/world/blocks/defense/turrets/Turret.java index 9d925af2f3..378b90da4e 100644 --- a/core/src/mindustry/world/blocks/defense/turrets/Turret.java +++ b/core/src/mindustry/world/blocks/defense/turrets/Turret.java @@ -432,7 +432,7 @@ public abstract class Turret extends Block{ fshootEffect.at(x + tr.x, y + tr.y, rotation); fsmokeEffect.at(x + tr.x, y + tr.y, rotation); - shootSound.at(tile, Mathf.random(0.9f, 1.1f)); + shootSound.at(x + tr.x, y + tr.y, 1); if(shootShake > 0){ Effect.shake(shootShake, shootShake, this); From eaf7a86bcec54e5eaec5038241e1c45f43439281 Mon Sep 17 00:00:00 2001 From: Patrick 'Quezler' Mounier Date: Sun, 11 Oct 2020 13:54:28 +0200 Subject: [PATCH 16/41] Make deconstructing scrap walls return scrap --- core/src/mindustry/content/Blocks.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index f04da239bb..35a49b7901 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -829,27 +829,27 @@ public class Blocks implements ContentList{ }}; scrapWall = new Wall("scrap-wall"){{ - requirements(Category.defense, BuildVisibility.sandboxOnly, with()); + requirements(Category.defense, BuildVisibility.sandboxOnly, with(Items.scrap, 6)); health = 60 * wallHealthMultiplier; variants = 5; }}; scrapWallLarge = new Wall("scrap-wall-large"){{ - requirements(Category.defense, BuildVisibility.sandboxOnly, with()); + requirements(Category.defense, BuildVisibility.sandboxOnly, ItemStack.mult(scrapWall.requirements, 4)); health = 60 * 4 * wallHealthMultiplier; size = 2; variants = 4; }}; scrapWallHuge = new Wall("scrap-wall-huge"){{ - requirements(Category.defense, BuildVisibility.sandboxOnly, with()); + requirements(Category.defense, BuildVisibility.sandboxOnly, ItemStack.mult(scrapWall.requirements, 9)); health = 60 * 9 * wallHealthMultiplier; size = 3; variants = 3; }}; scrapWallGigantic = new Wall("scrap-wall-gigantic"){{ - requirements(Category.defense, BuildVisibility.sandboxOnly, with()); + requirements(Category.defense, BuildVisibility.sandboxOnly, ItemStack.mult(scrapWall.requirements, 16)); health = 60 * 16 * wallHealthMultiplier; size = 4; }}; From a60ae3a0600e4c6be88a56c9d6db7fa4ee18e640 Mon Sep 17 00:00:00 2001 From: DeltaNedas Date: Sun, 11 Oct 2020 12:56:55 +0100 Subject: [PATCH 17/41] add names to major fragment elements --- .../mindustry/ui/fragments/HudFragment.java | 47 ++++++++++++++----- .../mindustry/ui/fragments/MenuFragment.java | 11 +++-- .../ui/fragments/PlayerListFragment.java | 5 ++ .../ui/fragments/ScriptConsoleFragment.java | 1 - 4 files changed, 46 insertions(+), 18 deletions(-) diff --git a/core/src/mindustry/ui/fragments/HudFragment.java b/core/src/mindustry/ui/fragments/HudFragment.java index 38ae0cd1f2..628ffbbd49 100644 --- a/core/src/mindustry/ui/fragments/HudFragment.java +++ b/core/src/mindustry/ui/fragments/HudFragment.java @@ -79,20 +79,23 @@ public class HudFragment extends Fragment{ //paused table parent.fill(t -> { + t.name = "paused"; t.top().visible(() -> state.isPaused()).touchable = Touchable.disabled; t.table(Styles.black5, top -> top.add("@paused").style(Styles.outlineLabel).pad(8f)).growX(); }); //minimap + position parent.fill(t -> { + t.name = "minimap/position"; t.visible(() -> Core.settings.getBool("minimap") && !state.rules.tutorial && shown); //minimap - t.add(new Minimap()); + t.add(new Minimap()).name("minimap"); t.row(); //position t.label(() -> player.tileX() + "," + player.tileY()) .visible(() -> Core.settings.getBool("position") && !state.rules.tutorial) - .touchable(Touchable.disabled); + .touchable(Touchable.disabled) + .name("position"); t.top().right(); }); @@ -104,15 +107,18 @@ public class HudFragment extends Fragment{ if(mobile){ cont.table(select -> { + select.name = "mobile buttons"; select.left(); select.defaults().size(dsize).left(); ImageButtonStyle style = Styles.clearTransi; - select.button(Icon.menu, style, ui.paused::show); + select.button(Icon.menu, style, ui.paused::show).name("menu"); flip = select.button(Icon.upOpen, style, this::toggleMenus).get(); + flip.name = "flip"; - select.button(Icon.paste, style, ui.schematics::show); + select.button(Icon.paste, style, ui.schematics::show) + .name("schematics"); select.button(Icon.pause, style, () -> { if(net.active()){ @@ -141,7 +147,7 @@ public class HudFragment extends Fragment{ }else{ ui.database.show(); } - }).update(i -> { + }).name("chat").update(i -> { if(net.active() && mobile){ i.getStyle().imageUp = Icon.chat; }else if(state.isCampaign()){ @@ -167,14 +173,15 @@ public class HudFragment extends Fragment{ Table wavesMain, editorMain; - cont.stack(wavesMain = new Table(), editorMain = new Table()).height(wavesMain.getPrefHeight()); + cont.stack(wavesMain = new Table(), editorMain = new Table()).height(wavesMain.getPrefHeight()) + .name("waves/editor"); wavesMain.visible(() -> shown && !state.isEditor()); - wavesMain.top().left(); + wavesMain.top().left().name = "waves"; wavesMain.table(s -> { //wave info button with text - s.add(makeStatusTable()).grow(); + s.add(makeStatusTable()).grow().name("status"); //table with button to skip wave s.button(Icon.play, Styles.righti, 30f, () -> { @@ -183,18 +190,22 @@ public class HudFragment extends Fragment{ }else{ logic.skipWave(); } - }).growY().fillX().right().width(40f).disabled(b -> !canSkipWave()).visible(() -> state.rules.waves); + }).growY().fillX().right().width(40f).disabled(b -> !canSkipWave()) + .visible(() -> state.rules.waves).name("skip"); }).width(dsize * 5 + 4f); wavesMain.row(); wavesMain.table(Tex.button, t -> t.margin(10f).add(new Bar("boss.health", Pal.health, () -> state.boss() == null ? 0f : state.boss().healthf()).blink(Color.white)) - .grow()).fillX().visible(() -> state.rules.waves && state.boss() != null).height(60f).get(); + .grow()).fillX().visible(() -> state.rules.waves && state.boss() != null).height(60f).get() + .name = "boss"; wavesMain.row(); + editorMain.name = "editor"; editorMain.table(Tex.buttonEdge4, t -> { //t.margin(0f); + t.name("teams"); t.add("@editor.teams").growX().left(); t.row(); t.table(teams -> { @@ -215,29 +226,33 @@ public class HudFragment extends Fragment{ }).width(dsize * 5 + 4f); editorMain.visible(() -> shown && state.isEditor()); - //fps display cont.table(info -> { + info.name = "fps/ping"; info.touchable = Touchable.disabled; info.top().left().margin(4).visible(() -> Core.settings.getBool("fps") && shown); info.update(() -> info.setTranslation(state.rules.waves || state.isEditor() ? 0f : -Scl.scl(dsize * 4 + 3), 0)); IntFormat fps = new IntFormat("fps"); IntFormat ping = new IntFormat("ping"); - info.label(() -> fps.get(Core.graphics.getFramesPerSecond())).left().style(Styles.outlineLabel); + info.label(() -> fps.get(Core.graphics.getFramesPerSecond())).left() + .style(Styles.outlineLabel).name("fps"); info.row(); - info.label(() -> ping.get(netClient.getPing())).visible(net::client).left().style(Styles.outlineLabel); + info.label(() -> ping.get(netClient.getPing())).visible(net::client).left() + .style(Styles.outlineLabel).name("ping"); }).top().left(); }); //core items parent.fill(t -> { + t.name = "coreitems"; t.top().add(coreItems); t.visible(() -> Core.settings.getBool("coreitems") && !mobile && !state.isPaused() && shown); }); //spawner warning parent.fill(t -> { + t.name = "nearpoint"; t.touchable = Touchable.disabled; t.table(Styles.black, c -> c.add("@nearpoint") .update(l -> l.setColor(Tmp.c1.set(Color.white).lerp(Color.scarlet, Mathf.absin(Time.time(), 10f, 1f)))) @@ -246,12 +261,14 @@ public class HudFragment extends Fragment{ }); parent.fill(t -> { + t.name = "waiting"; t.visible(() -> netServer.isWaitingForPlayers()); t.table(Tex.button, c -> c.add("@waiting.players")); }); //'core is under attack' table parent.fill(t -> { + t.name = "coreattack"; t.touchable = Touchable.disabled; float notifDuration = 240f; float[] coreAttackTime = {0}; @@ -285,6 +302,7 @@ public class HudFragment extends Fragment{ //tutorial text parent.fill(t -> { + t.name = "tutorial"; Runnable resize = () -> { t.clearChildren(); t.top().right().visible(() -> state.rules.tutorial); @@ -307,11 +325,13 @@ public class HudFragment extends Fragment{ //'saving' indicator parent.fill(t -> { + t.name = "saving"; t.bottom().visible(() -> control.saves.isSaving()); t.add("@saving").style(Styles.outlineLabel); }); parent.fill(p -> { + p.name = "hudtext"; p.top().table(Styles.black3, t -> t.margin(4).label(() -> hudText) .style(Styles.outlineLabel)).padTop(10).visible(p.color.a >= 0.001f); p.update(() -> { @@ -327,6 +347,7 @@ public class HudFragment extends Fragment{ //TODO DEBUG: rate table if(false) parent.fill(t -> { + t.name = "rates"; t.bottom().left(); t.table(Styles.black6, c -> { Bits used = new Bits(content.items().size); diff --git a/core/src/mindustry/ui/fragments/MenuFragment.java b/core/src/mindustry/ui/fragments/MenuFragment.java index 45faa9bf10..b4da23facf 100644 --- a/core/src/mindustry/ui/fragments/MenuFragment.java +++ b/core/src/mindustry/ui/fragments/MenuFragment.java @@ -45,6 +45,7 @@ public class MenuFragment extends Fragment{ parent.fill(c -> { container = c; + c.name = "menu container"; if(!mobile){ buildDesktop(); @@ -57,8 +58,8 @@ public class MenuFragment extends Fragment{ //info icon if(mobile){ - parent.fill(c -> c.bottom().left().button("", Styles.infot, ui.about::show).size(84, 45)); - parent.fill(c -> c.bottom().right().button("", Styles.discordt, ui.discord::show).size(84, 45)); + parent.fill(c -> c.bottom().left().button("", Styles.infot, ui.about::show).size(84, 45).name("info")); + parent.fill(c -> c.bottom().right().button("", Styles.discordt, ui.discord::show).size(84, 45).name("discord")); }else if(becontrol.active()){ parent.fill(c -> c.bottom().right().button("@be.check", Icon.refresh, () -> { ui.loadfrag.show(); @@ -68,7 +69,7 @@ public class MenuFragment extends Fragment{ ui.showInfo("@be.noupdates"); } }); - }).size(200, 60).update(t -> { + }).size(200, 60).name("becheck").update(t -> { t.getLabel().setColor(becontrol.isUpdateAvailable() ? Tmp.c1.set(Color.white).lerp(Pal.accent, Mathf.absin(5f, 1f)) : Color.white); })); } @@ -93,6 +94,7 @@ public class MenuFragment extends Fragment{ private void buildMobile(){ container.clear(); + container.name = "buttons"; container.setSize(Core.graphics.getWidth(), Core.graphics.getHeight()); float size = 120f; @@ -153,7 +155,6 @@ public class MenuFragment extends Fragment{ container.clear(); container.setSize(Core.graphics.getWidth(), Core.graphics.getHeight()); - float width = 230f; Drawable background = Styles.black6; @@ -161,6 +162,7 @@ public class MenuFragment extends Fragment{ container.add().width(Core.graphics.getWidth()/10f); container.table(background, t -> { t.defaults().width(width).height(70f); + t.name = "buttons"; buttons(t, new Buttoni("@play", Icon.play, @@ -183,6 +185,7 @@ public class MenuFragment extends Fragment{ container.table(background, t -> { submenu = t; + t.name = "submenu"; t.color.a = 0f; t.top(); t.defaults().width(width).height(70f); diff --git a/core/src/mindustry/ui/fragments/PlayerListFragment.java b/core/src/mindustry/ui/fragments/PlayerListFragment.java index eae9407131..c006dcf3ff 100644 --- a/core/src/mindustry/ui/fragments/PlayerListFragment.java +++ b/core/src/mindustry/ui/fragments/PlayerListFragment.java @@ -24,7 +24,9 @@ public class PlayerListFragment extends Fragment{ @Override public void build(Group parent){ + content.name = "players"; parent.fill(cont -> { + cont.name = "playerlist"; cont.visible(() -> visible); cont.update(() -> { if(!(net.active() && state.isGame())){ @@ -47,6 +49,7 @@ public class PlayerListFragment extends Fragment{ sField = pane.field(null, text -> { rebuild(); }).grow().pad(8).get(); + sField.name = "search"; sField.setMaxLength(maxNameLength); sField.setMessageText(Core.bundle.format("players.search")); @@ -56,6 +59,7 @@ public class PlayerListFragment extends Fragment{ pane.table(menu -> { menu.defaults().growX().height(50f).fillY(); + menu.name = "menu"; menu.button("@server.bans", ui.bans::show).disabled(b -> net.client()); menu.button("@server.admins", ui.admins::show).disabled(b -> net.client()); @@ -99,6 +103,7 @@ public class PlayerListFragment extends Fragment{ }; table.margin(8); table.add(new Image(user.icon()).setScaling(Scaling.bounded)).grow(); + table.name = user.name(); button.add(table).size(h); button.labelWrap("[#" + user.color().toString().toUpperCase() + "]" + user.name()).width(170f).pad(10); diff --git a/core/src/mindustry/ui/fragments/ScriptConsoleFragment.java b/core/src/mindustry/ui/fragments/ScriptConsoleFragment.java index 73861538e3..3f33dd1b4b 100644 --- a/core/src/mindustry/ui/fragments/ScriptConsoleFragment.java +++ b/core/src/mindustry/ui/fragments/ScriptConsoleFragment.java @@ -39,7 +39,6 @@ public class ScriptConsoleFragment extends Table{ }; public ScriptConsoleFragment(){ - setFillParent(true); font = Fonts.def; From 1539d8684690316394127be650748f127edd55c7 Mon Sep 17 00:00:00 2001 From: DeltaNedas Date: Sun, 11 Oct 2020 12:57:18 +0100 Subject: [PATCH 18/41] add names to some major dialog elements --- .../mindustry/ui/dialogs/PausedDialog.java | 7 ++-- .../mindustry/ui/dialogs/PlanetDialog.java | 25 +++++++------ .../mindustry/ui/dialogs/ResearchDialog.java | 36 +++++++++---------- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/core/src/mindustry/ui/dialogs/PausedDialog.java b/core/src/mindustry/ui/dialogs/PausedDialog.java index 559450a591..2d95ee6f6b 100644 --- a/core/src/mindustry/ui/dialogs/PausedDialog.java +++ b/core/src/mindustry/ui/dialogs/PausedDialog.java @@ -38,14 +38,15 @@ public class PausedDialog extends BaseDialog{ cont.label(() -> state.getSector() == null ? "" : ("[lightgray]Next turn in [accent]" + state.getSector().displayTimeRemaining() + (state.rules.winWave > 0 && !state.getSector().isCaptured() ? "\n[lightgray]Reach wave[accent] " + state.rules.winWave + "[] to capture" : ""))) - .visible(() -> state.getSector() != null).colspan(2); + .visible(() -> state.getSector() != null).colspan(2) + .name("turn"); cont.row(); float dw = 220f; cont.defaults().width(dw).height(55).pad(5f); - cont.button("@back", Icon.left, this::hide); - cont.button("@settings", Icon.settings, ui.settings::show); + cont.button("@back", Icon.left, this::hide).name("back"); + cont.button("@settings", Icon.settings, ui.settings::show).name("settings"); if(!state.rules.tutorial){ if(!state.isCampaign() && !state.isEditor()){ diff --git a/core/src/mindustry/ui/dialogs/PlanetDialog.java b/core/src/mindustry/ui/dialogs/PlanetDialog.java index a7b667dcd8..02ab020841 100644 --- a/core/src/mindustry/ui/dialogs/PlanetDialog.java +++ b/core/src/mindustry/ui/dialogs/PlanetDialog.java @@ -32,18 +32,18 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ //if true, enables launching anywhere for testing public static boolean debugSelect = false; - final FrameBuffer buffer = new FrameBuffer(2, 2, true); - final PlanetRenderer planets = renderer.planets; - final LaunchLoadoutDialog loadouts = new LaunchLoadoutDialog(); - final Table stable = new Table().background(Styles.black3); + public final FrameBuffer buffer = new FrameBuffer(2, 2, true); + public final PlanetRenderer planets = renderer.planets; + public final LaunchLoadoutDialog loadouts = new LaunchLoadoutDialog(); + public final Table stable = new Table().background(Styles.black3); - int launchRange; - float zoom = 1f, selectAlpha = 1f; - @Nullable Sector selected, hovered, launchSector; - CoreBuild launcher; - Mode mode = look; - boolean launching; - Cons listener = s -> {}; + public int launchRange; + public float zoom = 1f, selectAlpha = 1f; + public @Nullable Sector selected, hovered, launchSector; + public CoreBuild launcher; + public Mode mode = look; + public boolean launching; + public Cons listener = s -> {}; public PlanetDialog(){ super("", Styles.fullDialog); @@ -237,7 +237,6 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ cont.clear(); titleTable.remove(); - cont.stack( new Element(){ { @@ -468,7 +467,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ stable.act(0f); } - enum Mode{ + public enum Mode{ /** Look around for existing sectors. Can only deploy. */ look, /** Launch to a new location. */ diff --git a/core/src/mindustry/ui/dialogs/ResearchDialog.java b/core/src/mindustry/ui/dialogs/ResearchDialog.java index a87aa2d55c..b1dbea2528 100644 --- a/core/src/mindustry/ui/dialogs/ResearchDialog.java +++ b/core/src/mindustry/ui/dialogs/ResearchDialog.java @@ -31,14 +31,14 @@ import java.util.*; import static mindustry.Vars.*; public class ResearchDialog extends BaseDialog{ - final float nodeSize = Scl.scl(60f); - ObjectSet nodes = new ObjectSet<>(); - TechTreeNode root = new TechTreeNode(TechTree.root, null); - Rect bounds = new Rect(); - ItemsDisplay itemDisplay; - View view; + public final float nodeSize = Scl.scl(60f); + public ObjectSet nodes = new ObjectSet<>(); + public TechTreeNode root = new TechTreeNode(TechTree.root, null); + public Rect bounds = new Rect(); + public ItemsDisplay itemDisplay; + public View view; - ItemSeq items; + public ItemSeq items; public ResearchDialog(){ super(""); @@ -114,7 +114,7 @@ public class ResearchDialog extends BaseDialog{ buttons.button("@database", Icon.book, () -> { hide(); ui.database.show(); - }).size(210f, 64f); + }).size(210f, 64f).name("database"); //scaling/drag input addListener(new InputListener(){ @@ -250,7 +250,7 @@ public class ResearchDialog extends BaseDialog{ return node.content.unlocked() || !node.objectives.contains(i -> !i.complete()); } - void showToast(String info){ + public void showToast(String info){ Table table = new Table(); table.actions(Actions.fadeOut(0.5f, Interp.fade), Actions.remove()); table.top().add(info); @@ -279,11 +279,11 @@ public class ResearchDialog extends BaseDialog{ } } - class TechTreeNode extends TreeNode{ - final TechNode node; - boolean visible = true, selectable = true; + public class TechTreeNode extends TreeNode{ + public final TechNode node; + public boolean visible = true, selectable = true; - TechTreeNode(TechNode node, TechTreeNode parent){ + public TechTreeNode(TechNode node, TechTreeNode parent){ this.node = node; this.parent = parent; this.width = this.height = nodeSize; @@ -297,11 +297,11 @@ public class ResearchDialog extends BaseDialog{ } } - class View extends Group{ - float panX = 0, panY = -200, lastZoom = -1; - boolean moved = false; - ImageButton hoverNode; - Table infoTable = new Table(); + public class View extends Group{ + public float panX = 0, panY = -200, lastZoom = -1; + public boolean moved = false; + public ImageButton hoverNode; + public Table infoTable = new Table(); { infoTable.touchable = Touchable.enabled; From 5eb8a8752818f815a05872d4aeb36efe20202ce2 Mon Sep 17 00:00:00 2001 From: DeltaNedas Date: Sun, 11 Oct 2020 12:59:00 +0100 Subject: [PATCH 19/41] h --- core/src/mindustry/ui/fragments/MenuFragment.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/mindustry/ui/fragments/MenuFragment.java b/core/src/mindustry/ui/fragments/MenuFragment.java index b4da23facf..cd8d13be0d 100644 --- a/core/src/mindustry/ui/fragments/MenuFragment.java +++ b/core/src/mindustry/ui/fragments/MenuFragment.java @@ -45,7 +45,7 @@ public class MenuFragment extends Fragment{ parent.fill(c -> { container = c; - c.name = "menu container"; + c.name = "menu container"; if(!mobile){ buildDesktop(); @@ -94,7 +94,7 @@ public class MenuFragment extends Fragment{ private void buildMobile(){ container.clear(); - container.name = "buttons"; + container.name = "buttons"; container.setSize(Core.graphics.getWidth(), Core.graphics.getHeight()); float size = 120f; @@ -162,7 +162,7 @@ public class MenuFragment extends Fragment{ container.add().width(Core.graphics.getWidth()/10f); container.table(background, t -> { t.defaults().width(width).height(70f); - t.name = "buttons"; + t.name = "buttons"; buttons(t, new Buttoni("@play", Icon.play, @@ -185,7 +185,7 @@ public class MenuFragment extends Fragment{ container.table(background, t -> { submenu = t; - t.name = "submenu"; + t.name = "submenu"; t.color.a = 0f; t.top(); t.defaults().width(width).height(70f); From a975da543b105778ef1220c230f652d6dab51964 Mon Sep 17 00:00:00 2001 From: Patrick 'Quezler' Mounier Date: Sun, 11 Oct 2020 14:58:53 +0200 Subject: [PATCH 20/41] Add a connections bar to powernodes Bundle entry in next commit. --- core/src/mindustry/world/blocks/power/PowerNode.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/src/mindustry/world/blocks/power/PowerNode.java b/core/src/mindustry/world/blocks/power/PowerNode.java index 245c3d4f7e..8654d8d802 100644 --- a/core/src/mindustry/world/blocks/power/PowerNode.java +++ b/core/src/mindustry/world/blocks/power/PowerNode.java @@ -112,6 +112,12 @@ public class PowerNode extends PowerBlock{ (UI.formatAmount((int)entity.power.graph.getLastPowerStored())), UI.formatAmount((int)entity.power.graph.getLastCapacity())), () -> Pal.powerBar, () -> Mathf.clamp(entity.power.graph.getLastPowerStored() / entity.power.graph.getLastCapacity()))); + + bars.add("connections", entity -> new Bar(() -> + Core.bundle.format("bar.powerlines", entity.power.links.size, maxNodes), + () -> Pal.ammo, + () -> (float)entity.power.links.size / (float)maxNodes + )); } @Override From 6d632fc53223d1c3dd0ac7868c2863f6f65b23d5 Mon Sep 17 00:00:00 2001 From: Patrick 'Quezler' Mounier Date: Sun, 11 Oct 2020 14:59:44 +0200 Subject: [PATCH 21/41] Update bundle.properties --- core/assets/bundles/bundle.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 6d1aafb54f..1c50a6a408 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -628,6 +628,7 @@ bar.powerbalance = Power: {0}/s bar.powerstored = Stored: {0}/{1} bar.poweramount = Power: {0} bar.poweroutput = Power Output: {0} +bar.powerlines = Connections: {0}/{1} bar.items = Items: {0} bar.capacity = Capacity: {0} bar.unitcap = {0} {1}/{2} From 65d9978fa10b4f092d6414d7b5a4db51babb0462 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 11 Oct 2020 09:02:20 -0400 Subject: [PATCH 22/41] Fixed #2901 / Fixed #2903 --- core/src/mindustry/content/Blocks.java | 2 ++ core/src/mindustry/core/Logic.java | 8 ++++---- core/src/mindustry/game/Universe.java | 5 +++-- core/src/mindustry/input/DesktopInput.java | 2 +- core/src/mindustry/ui/fragments/MinimapFragment.java | 2 +- core/src/mindustry/world/Block.java | 4 +++- core/src/mindustry/world/blocks/storage/CoreBlock.java | 7 +++++++ 7 files changed, 21 insertions(+), 9 deletions(-) diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index f04da239bb..4f684b0d2b 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -1341,6 +1341,7 @@ public class Blocks implements ContentList{ size = 4; unitCapModifier = 14; + researchCostMultiplier = 0.04f; }}; coreNucleus = new CoreBlock("core-nucleus"){{ @@ -1352,6 +1353,7 @@ public class Blocks implements ContentList{ size = 5; unitCapModifier = 20; + researchCostMultiplier = 0.06f; }}; vault = new StorageBlock("vault"){{ diff --git a/core/src/mindustry/core/Logic.java b/core/src/mindustry/core/Logic.java index dd54bcc59d..f49133e7d1 100644 --- a/core/src/mindustry/core/Logic.java +++ b/core/src/mindustry/core/Logic.java @@ -9,7 +9,6 @@ import mindustry.game.EventType.*; import mindustry.game.*; import mindustry.game.Teams.*; import mindustry.gen.*; -import mindustry.maps.*; import mindustry.type.*; import mindustry.type.Weather.*; import mindustry.world.*; @@ -93,9 +92,10 @@ public class Logic implements ApplicationListener{ //apply fractional damage based on how many turns have passed for this sector float turnsPassed = seconds / (turnDuration / 60f); - if(state.rules.sector.hasWaves() && turnsPassed > 0 && state.rules.sector.hasBase()){ - SectorDamage.apply(turnsPassed / sectorDestructionTurns); - } + //TODO sector damage disabled for now + //if(state.rules.sector.hasWaves() && turnsPassed > 0 && state.rules.sector.hasBase()){ + // SectorDamage.apply(turnsPassed / sectorDestructionTurns); + //} //add resources based on turns passed if(state.rules.sector.save != null && core != null){ diff --git a/core/src/mindustry/game/Universe.java b/core/src/mindustry/game/Universe.java index e64b4cfc07..892b93b731 100644 --- a/core/src/mindustry/game/Universe.java +++ b/core/src/mindustry/game/Universe.java @@ -140,8 +140,9 @@ public class Universe{ if(!sector.isBeingPlayed()){ sector.setSecondsPassed(sector.getSecondsPassed() + actuallyPassed); + //TODO sector damage disabled for now //check if the sector has been attacked too many times... - if(sector.hasBase() && sector.hasWaves() && sector.getSecondsPassed() * 60f > turnDuration * sectorDestructionTurns){ + /*if(sector.hasBase() && sector.hasWaves() && sector.getSecondsPassed() * 60f > turnDuration * sectorDestructionTurns){ //fire event for losing the sector Events.fire(new SectorLoseEvent(sector)); @@ -151,7 +152,7 @@ public class Universe{ //clear recieved sector.setExtraItems(new ItemSeq()); sector.save = null; - } + }*/ } //export to another sector diff --git a/core/src/mindustry/input/DesktopInput.java b/core/src/mindustry/input/DesktopInput.java index 0b21a2cea4..7099f254dd 100644 --- a/core/src/mindustry/input/DesktopInput.java +++ b/core/src/mindustry/input/DesktopInput.java @@ -176,7 +176,7 @@ public class DesktopInput extends InputHandler{ public void update(){ super.update(); - if(net.active() && Core.input.keyTap(Binding.player_list) && (scene.getKeyboardFocus() == null || scene.getKeyboardFocus().isDescendantOf(ui.listfrag.content))){ + if(net.active() && Core.input.keyTap(Binding.player_list) && (scene.getKeyboardFocus() == null || scene.getKeyboardFocus().isDescendantOf(ui.listfrag.content) || scene.getKeyboardFocus().isDescendantOf(ui.minimapfrag.elem))){ ui.listfrag.toggle(); } diff --git a/core/src/mindustry/ui/fragments/MinimapFragment.java b/core/src/mindustry/ui/fragments/MinimapFragment.java index 7c9d3b5994..43ad3163b0 100644 --- a/core/src/mindustry/ui/fragments/MinimapFragment.java +++ b/core/src/mindustry/ui/fragments/MinimapFragment.java @@ -18,7 +18,7 @@ public class MinimapFragment extends Fragment{ private boolean shown; float panx, pany, zoom = 1f, lastZoom = -1; private float baseSize = Scl.scl(5f); - private Element elem; + public Element elem; @Override public void build(Group parent){ diff --git a/core/src/mindustry/world/Block.java b/core/src/mindustry/world/Block.java index 189a9c21c1..95d9a426e0 100644 --- a/core/src/mindustry/world/Block.java +++ b/core/src/mindustry/world/Block.java @@ -193,6 +193,8 @@ public class Block extends UnlockableContent{ public BuildPlaceability buildPlaceability = BuildPlaceability.always; /** Multiplier for speed of building this block. */ public float buildCostMultiplier = 1f; + /** Multiplier for cost of research in tech tree. */ + public float researchCostMultiplier = 1; /** Whether this block has instant transfer.*/ public boolean instantTransfer = false; /** Whether you can rotate this block with Keybind rotateplaced + Scroll Wheel. */ @@ -619,7 +621,7 @@ public class Block extends UnlockableContent{ public ItemStack[] researchRequirements(){ ItemStack[] out = new ItemStack[requirements.length]; for(int i = 0; i < out.length; i++){ - int quantity = 40 + Mathf.round(Mathf.pow(requirements[i].amount, 1.25f) * 20, 10); + int quantity = 40 + Mathf.round(Mathf.pow(requirements[i].amount, 1.25f) * 20 * researchCostMultiplier, 10); out[i] = new ItemStack(requirements[i].item, UI.roundAmount(quantity)); } diff --git a/core/src/mindustry/world/blocks/storage/CoreBlock.java b/core/src/mindustry/world/blocks/storage/CoreBlock.java index 14d60280ee..8d656a95d2 100644 --- a/core/src/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/mindustry/world/blocks/storage/CoreBlock.java @@ -14,6 +14,7 @@ import mindustry.game.EventType.*; import mindustry.game.*; import mindustry.gen.*; import mindustry.graphics.*; +import mindustry.logic.*; import mindustry.type.*; import mindustry.ui.*; import mindustry.world.*; @@ -159,6 +160,12 @@ public class CoreBlock extends StorageBlock{ public BlockUnitc unit = Nulls.blockUnit; public boolean noEffect = false; + @Override + public double sense(LAccess sensor){ + if(sensor == LAccess.itemCapacity) return storageCapacity; + return super.sense(sensor); + } + @Override public void created(){ unit = (BlockUnitc)UnitTypes.block.create(team); From 62baf5cab2b815aedc0e2668b8fba868a1714462 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 11 Oct 2020 09:24:27 -0400 Subject: [PATCH 23/41] Update core/src/mindustry/world/blocks/power/PowerNode.java Co-authored-by: Patrick 'Quezler' Mounier --- core/src/mindustry/world/blocks/power/PowerNode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/mindustry/world/blocks/power/PowerNode.java b/core/src/mindustry/world/blocks/power/PowerNode.java index 8654d8d802..5d033c99b7 100644 --- a/core/src/mindustry/world/blocks/power/PowerNode.java +++ b/core/src/mindustry/world/blocks/power/PowerNode.java @@ -115,7 +115,7 @@ public class PowerNode extends PowerBlock{ bars.add("connections", entity -> new Bar(() -> Core.bundle.format("bar.powerlines", entity.power.links.size, maxNodes), - () -> Pal.ammo, + () -> Pal.items, () -> (float)entity.power.links.size / (float)maxNodes )); } From 0f2c38b0c0ac9402fe28ac758b1c3dd189394301 Mon Sep 17 00:00:00 2001 From: DeltaNedas Date: Sun, 11 Oct 2020 15:28:50 +0100 Subject: [PATCH 24/41] oh no --- core/src/mindustry/ui/fragments/HudFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/mindustry/ui/fragments/HudFragment.java b/core/src/mindustry/ui/fragments/HudFragment.java index 628ffbbd49..6f8b38832d 100644 --- a/core/src/mindustry/ui/fragments/HudFragment.java +++ b/core/src/mindustry/ui/fragments/HudFragment.java @@ -205,7 +205,7 @@ public class HudFragment extends Fragment{ editorMain.name = "editor"; editorMain.table(Tex.buttonEdge4, t -> { //t.margin(0f); - t.name("teams"); + t.name = "teams"; t.add("@editor.teams").growX().left(); t.row(); t.table(teams -> { From 5bcc37d06107ab65b40fda82ea9dfc5f965c0206 Mon Sep 17 00:00:00 2001 From: Somka000 <51973243+Somka000@users.noreply.github.com> Date: Sun, 11 Oct 2020 16:49:27 +0200 Subject: [PATCH 25/41] Update servers_be.json I created PvP server on BE, because players don't have PvP BE server and on BE version are new turrets, better logic etc. --- servers_be.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/servers_be.json b/servers_be.json index 5ebfae37df..312bc9da30 100644 --- a/servers_be.json +++ b/servers_be.json @@ -7,5 +7,8 @@ }, { "address": "md.surrealment.com" + }, + { + "address": "mindustry.pl:6660" } ] From 3d99e38f10b73bba8a2fba97c27ec5e6e3e5f3de Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 11 Oct 2020 10:51:33 -0400 Subject: [PATCH 26/41] Sector simplification --- core/assets/bundles/bundle.properties | 2 ++ core/assets/maps/craters.msav | Bin 11757 -> 11971 bytes core/src/mindustry/Vars.java | 2 +- core/src/mindustry/content/StatusEffects.java | 14 ++++++------ core/src/mindustry/core/Logic.java | 4 +++- .../mindustry/entities/comp/ShieldComp.java | 3 ++- .../mindustry/entities/comp/StatusComp.java | 6 ++--- core/src/mindustry/game/Objectives.java | 5 +++-- core/src/mindustry/game/SpawnGroup.java | 14 ++++++++---- core/src/mindustry/type/StatusEffect.java | 4 ++-- .../mindustry/ui/dialogs/PausedDialog.java | 9 ++++---- .../mindustry/ui/dialogs/PlanetDialog.java | 7 ++++-- .../mindustry/ui/fragments/HudFragment.java | 21 ++++++++++++++++++ 13 files changed, 64 insertions(+), 27 deletions(-) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 6d1aafb54f..3f4cc635fe 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -291,6 +291,8 @@ waiting = [lightgray]Waiting... waiting.players = Waiting for players... wave.enemies = [lightgray]{0} Enemies Remaining wave.enemy = [lightgray]{0} Enemy Remaining +wave.guardianwarn = Guardian approaching in [accent]{0}[] waves. +wave.guardianwarn.one = Guardian approaching in [accent]{0}[] wave. loadimage = Load Image saveimage = Save Image unknown = Unknown diff --git a/core/assets/maps/craters.msav b/core/assets/maps/craters.msav index b879701ae6bf4dd86e0831622f05cd11e168e550..b10b354bf009d65f7a94e7eda8c95064d58f0599 100644 GIT binary patch literal 11971 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 V=ImQ{cE7pxKmK+5{{gK4>XOux*mM8@ literal 11757 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 { @@ -81,7 +81,7 @@ public class StatusEffects implements ContentList{ melting = new StatusEffect("melting"){{ speedMultiplier = 0.8f; - armorMultiplier = 0.8f; + healthMultiplier = 0.8f; damage = 0.3f; effect = Fx.melting; @@ -93,7 +93,7 @@ public class StatusEffects implements ContentList{ sapped = new StatusEffect("sapped"){{ speedMultiplier = 0.7f; - armorMultiplier = 0.8f; + healthMultiplier = 0.8f; effect = Fx.sapped; effectChance = 0.1f; }}; @@ -115,7 +115,7 @@ public class StatusEffects implements ContentList{ }}; overdrive = new StatusEffect("overdrive"){{ - armorMultiplier = 0.95f; + healthMultiplier = 0.95f; speedMultiplier = 1.15f; damageMultiplier = 1.4f; damage = -0.01f; @@ -132,13 +132,13 @@ public class StatusEffects implements ContentList{ }}; shielded = new StatusEffect("shielded"){{ - armorMultiplier = 3f; + healthMultiplier = 3f; }}; boss = new StatusEffect("boss"){{ permanent = true; - damageMultiplier = 1.5f; - armorMultiplier = 1.5f; + damageMultiplier = 2f; + healthMultiplier = 2f; }}; shocked = new StatusEffect("shocked"); diff --git a/core/src/mindustry/core/Logic.java b/core/src/mindustry/core/Logic.java index f49133e7d1..31dee47410 100644 --- a/core/src/mindustry/core/Logic.java +++ b/core/src/mindustry/core/Logic.java @@ -197,6 +197,8 @@ public class Logic implements ApplicationListener{ state.rules.waves = false; } + //TODO capturing is disabled + /* //if there's a "win" wave and no enemies are present, win automatically if(state.rules.waves && state.enemies == 0 && state.rules.winWave > 0 && state.wave >= state.rules.winWave && !spawner.isSpawning()){ //the sector has been conquered - waves get disabled @@ -209,7 +211,7 @@ public class Logic implements ApplicationListener{ if(!headless){ control.saves.saveSector(state.rules.sector); } - } + }*/ }else{ if(!state.rules.attackMode && state.teams.playerCores().size == 0 && !state.gameOver){ state.gameOver = true; diff --git a/core/src/mindustry/entities/comp/ShieldComp.java b/core/src/mindustry/entities/comp/ShieldComp.java index 359637414e..274286b801 100644 --- a/core/src/mindustry/entities/comp/ShieldComp.java +++ b/core/src/mindustry/entities/comp/ShieldComp.java @@ -9,7 +9,7 @@ import static mindustry.Vars.*; @Component abstract class ShieldComp implements Healthc, Posc{ - @Import float health, hitTime, x, y; + @Import float health, hitTime, x, y, healthMultiplier; @Import boolean dead; /** Absorbs health damage. */ @@ -22,6 +22,7 @@ abstract class ShieldComp implements Healthc, Posc{ @Replace @Override public void damage(float amount){ + amount /= healthMultiplier; //apply armor amount = Math.max(amount - armor, minArmorDamage * amount); diff --git a/core/src/mindustry/entities/comp/StatusComp.java b/core/src/mindustry/entities/comp/StatusComp.java index 3a31b13b95..fcce0d0a02 100644 --- a/core/src/mindustry/entities/comp/StatusComp.java +++ b/core/src/mindustry/entities/comp/StatusComp.java @@ -19,7 +19,7 @@ abstract class StatusComp implements Posc, Flyingc{ private Seq statuses = new Seq<>(); private transient Bits applied = new Bits(content.getBy(ContentType.status).size); - @ReadOnly transient float speedMultiplier = 1, damageMultiplier = 1, armorMultiplier = 1, reloadMultiplier = 1; + @ReadOnly transient float speedMultiplier = 1, damageMultiplier = 1, healthMultiplier = 1, reloadMultiplier = 1; @Import UnitType type; @@ -104,7 +104,7 @@ abstract class StatusComp implements Posc, Flyingc{ } applied.clear(); - speedMultiplier = damageMultiplier = armorMultiplier = reloadMultiplier = 1f; + speedMultiplier = damageMultiplier = healthMultiplier = reloadMultiplier = 1f; if(statuses.isEmpty()) return; @@ -122,7 +122,7 @@ abstract class StatusComp implements Posc, Flyingc{ statuses.remove(index); }else{ speedMultiplier *= entry.effect.speedMultiplier; - armorMultiplier *= entry.effect.armorMultiplier; + healthMultiplier *= entry.effect.healthMultiplier; damageMultiplier *= entry.effect.damageMultiplier; reloadMultiplier *= entry.effect.reloadMultiplier; entry.effect.update(self(), entry.time); diff --git a/core/src/mindustry/game/Objectives.java b/core/src/mindustry/game/Objectives.java index 535f1d3e13..a4097c51fc 100644 --- a/core/src/mindustry/game/Objectives.java +++ b/core/src/mindustry/game/Objectives.java @@ -28,6 +28,7 @@ public class Objectives{ } } + //TODO fix public static class SectorComplete extends SectorObjective{ public SectorComplete(SectorPreset zone){ @@ -38,12 +39,12 @@ public class Objectives{ @Override public boolean complete(){ - return preset.sector.isCaptured(); + return preset.sector.save != null && preset.sector.save.meta.wave >= preset.sector.save.meta.rules.winWave; } @Override public String display(){ - return Core.bundle.format("requirement.capture", preset.localizedName); + return Core.bundle.format("requirement.wave", preset.sector.save == null ? "" : preset.sector.save.meta.rules.winWave, preset.localizedName); } } diff --git a/core/src/mindustry/game/SpawnGroup.java b/core/src/mindustry/game/SpawnGroup.java index 28edfd0a1a..f9ae7c74d3 100644 --- a/core/src/mindustry/game/SpawnGroup.java +++ b/core/src/mindustry/game/SpawnGroup.java @@ -28,7 +28,7 @@ public class SpawnGroup implements Serializable{ /** The spacing, in waves, of spawns. For example, 2 = spawns every other wave */ public int spacing = 1; /** Maximum amount of units that spawn */ - public int max = 100; + public int max = 40; /** How many waves need to pass before the amount of units spawned increases by 1 */ public float unitScaling = never; /** Shield points that this unit has. */ @@ -88,7 +88,7 @@ public class SpawnGroup implements Serializable{ if(begin != 0) json.writeValue("begin", begin); if(end != never) json.writeValue("end", end); if(spacing != 1) json.writeValue("spacing", spacing); - //if(max != 40) json.writeValue("max", max); + if(max != 40) json.writeValue("max", max); if(unitScaling != never) json.writeValue("scaling", unitScaling); if(shields != 0) json.writeValue("shields", shields); if(shieldScaling != 0) json.writeValue("shieldScaling", shieldScaling); @@ -105,12 +105,18 @@ public class SpawnGroup implements Serializable{ begin = data.getInt("begin", 0); end = data.getInt("end", never); spacing = data.getInt("spacing", 1); - //max = data.getInt("max", 40); + max = data.getInt("max", 40); unitScaling = data.getFloat("scaling", never); shields = data.getFloat("shields", 0); shieldScaling = data.getFloat("shieldScaling", 0); unitAmount = data.getInt("amount", 1); - effect = content.getByName(ContentType.status, data.hasChild("effect") && data.getChild("effect").isString() ? data.getString("effect", "none") : "none"); + + //old boss effect ID + if(data.has("effect") && data.get("effect").isNumber() && data.getInt("effect", -1) == 8){ + effect = StatusEffects.boss; + }else{ + effect = content.getByName(ContentType.status, data.has("effect") && data.get("effect").isString() ? data.getString("effect", "none") : "none"); + } } @Override diff --git a/core/src/mindustry/type/StatusEffect.java b/core/src/mindustry/type/StatusEffect.java index fda8dbbbf2..eb0bedb60c 100644 --- a/core/src/mindustry/type/StatusEffect.java +++ b/core/src/mindustry/type/StatusEffect.java @@ -13,8 +13,8 @@ import mindustry.gen.*; public class StatusEffect extends MappableContent{ /** Damage dealt by the unit with the effect. */ public float damageMultiplier = 1f; - /** Unit armor multiplier. */ - public float armorMultiplier = 1f; + /** Unit health multiplier. */ + public float healthMultiplier = 1f; /** Unit speed multiplier */ public float speedMultiplier = 1f; /** Unit speed multiplier */ diff --git a/core/src/mindustry/ui/dialogs/PausedDialog.java b/core/src/mindustry/ui/dialogs/PausedDialog.java index 559450a591..664d4df92a 100644 --- a/core/src/mindustry/ui/dialogs/PausedDialog.java +++ b/core/src/mindustry/ui/dialogs/PausedDialog.java @@ -35,10 +35,11 @@ public class PausedDialog extends BaseDialog{ if(!mobile){ //TODO localize - cont.label(() -> state.getSector() == null ? "" : - ("[lightgray]Next turn in [accent]" + state.getSector().displayTimeRemaining() + - (state.rules.winWave > 0 && !state.getSector().isCaptured() ? "\n[lightgray]Reach wave[accent] " + state.rules.winWave + "[] to capture" : ""))) - .visible(() -> state.getSector() != null).colspan(2); + //TODO capturing is disabled, remove? + //cont.label(() -> state.getSector() == null ? "" : + //("[lightgray]Next turn in [accent]" + state.getSector().displayTimeRemaining() + + // (state.rules.winWave > 0 && !state.getSector().isCaptured() ? "\n[lightgray]Reach wave[accent] " + state.rules.winWave + "[] to capture" : ""))) + // .visible(() -> state.getSector() != null).colspan(2); cont.row(); float dw = 220f; diff --git a/core/src/mindustry/ui/dialogs/PlanetDialog.java b/core/src/mindustry/ui/dialogs/PlanetDialog.java index a7b667dcd8..999c12035f 100644 --- a/core/src/mindustry/ui/dialogs/PlanetDialog.java +++ b/core/src/mindustry/ui/dialogs/PlanetDialog.java @@ -263,9 +263,10 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ } }, new Table(t -> { + t.touchable = Touchable.disabled; //TODO localize t.top(); - t.label(() -> mode == select ? "@sectors.select" : mode == launch ? "Select Launch Sector" : "Turn " + universe.turn()).style(Styles.outlineLabel).color(Pal.accent); + t.label(() -> mode == select ? "@sectors.select" : mode == launch ? "Select Launch Sector" : "").style(Styles.outlineLabel).color(Pal.accent); })).grow(); } @@ -338,6 +339,8 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ stable.add("[accent]Difficulty: " + (int)(sector.baseCoverage * 10)).row(); } + //TODO sector damage is disabled, remove when finalized + /* if(sector.hasBase() && sector.hasWaves()){ //TODO localize when finalized //these mechanics are likely to change and as such are not added to the bundle @@ -345,7 +348,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ stable.row(); stable.add("[accent]" + Mathf.ceil(sectorDestructionTurns - (sector.getSecondsPassed() * 60) / turnDuration) + " turn(s)\nuntil destruction"); stable.row(); - } + }*/ if(sector.save != null){ stable.add("@sectors.resources").row(); diff --git a/core/src/mindustry/ui/fragments/HudFragment.java b/core/src/mindustry/ui/fragments/HudFragment.java index 38ae0cd1f2..4c76976ec5 100644 --- a/core/src/mindustry/ui/fragments/HudFragment.java +++ b/core/src/mindustry/ui/fragments/HudFragment.java @@ -15,6 +15,7 @@ import arc.scene.ui.layout.*; import arc.struct.*; import arc.util.*; import mindustry.annotations.Annotations.*; +import mindustry.content.*; import mindustry.core.GameState.*; import mindustry.ctype.*; import mindustry.game.EventType.*; @@ -47,6 +48,26 @@ public class HudFragment extends Fragment{ @Override public void build(Group parent){ + //warn about guardian/boss waves + Events.on(WaveEvent.class, e -> { + int max = 10; + outer: + for(int i = state.wave - 1; i <= state.wave + max; i++){ + for(SpawnGroup group : state.rules.spawns){ + if(group.effect == StatusEffects.boss && group.getUnitsSpawned(i) > 0){ + int diff = (i + 2) - state.wave; + + //increments at which to warn about incoming guardian + if(diff == 1 || diff == 2 || diff == 5 || diff == 10){ + showToast(Icon.warning, Core.bundle.format("wave.guardianwarn" + (diff == 1 ? ".one" : ""), diff)); + } + + break outer; + } + } + } + }); + //TODO details and stuff Events.on(SectorCaptureEvent.class, e ->{ //TODO localize From 3fe79531a67c67aca9b7f417301cd83efe0acd3c Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 11 Oct 2020 11:47:22 -0400 Subject: [PATCH 27/41] Added message for last accessed player of block --- core/assets/bundles/bundle.properties | 1 + core/src/mindustry/ai/types/SuicideAI.java | 8 ++++++-- core/src/mindustry/content/Blocks.java | 2 +- core/src/mindustry/entities/comp/BuildingComp.java | 10 ++++++++++ core/src/mindustry/entities/comp/PayloadComp.java | 10 ++++++---- core/src/mindustry/input/InputHandler.java | 4 ++-- core/src/mindustry/world/blocks/ConstructBlock.java | 6 +++++- 7 files changed, 31 insertions(+), 10 deletions(-) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index ec0ca247ad..70d7430557 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -575,6 +575,7 @@ info.title = Info error.title = [scarlet]An error has occured error.crashtitle = An error has occured unit.nobuild = [scarlet]Unit can't build +lastaccessed = [lightgray]Last Accessed: {0} blocks.input = Input blocks.output = Output blocks.booster = Booster diff --git a/core/src/mindustry/ai/types/SuicideAI.java b/core/src/mindustry/ai/types/SuicideAI.java index 789fb93f4b..2eae6e409f 100644 --- a/core/src/mindustry/ai/types/SuicideAI.java +++ b/core/src/mindustry/ai/types/SuicideAI.java @@ -28,7 +28,7 @@ public class SuicideAI extends GroundAI{ boolean rotate = false, shoot = false, moveToTarget = false; - if(!Units.invalidateTarget(target, unit, unit.range())){ + if(!Units.invalidateTarget(target, unit, unit.range()) && unit.hasWeapons()){ rotate = true; shoot = unit.within(target, unit.type().weapons.first().bullet.range() + (target instanceof Building ? ((Building)target).block.size * Vars.tilesize / 2f : ((Hitboxc)target).hitSize() / 2f)); @@ -38,7 +38,11 @@ public class SuicideAI extends GroundAI{ } //do not move toward walls or transport blocks - if(!(target instanceof Building build && (build.block.group == BlockGroup.walls || build.block.group == BlockGroup.liquids || build.block.group == BlockGroup.transportation))){ + if(!(target instanceof Building build && ( + build.block.group == BlockGroup.walls || + build.block.group == BlockGroup.liquids || + build.block.group == BlockGroup.transportation + ))){ blockedByBlock = false; //raycast for target diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 4f684b0d2b..51412a7ed2 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -994,7 +994,7 @@ public class Blocks implements ContentList{ router = new Router("router"){{ requirements(Category.distribution, with(Items.copper, 3)); - buildCostMultiplier = 2f; + buildCostMultiplier = 4f; }}; distributor = new Router("distributor"){{ diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index 3a6c0ea8f0..15d79a8942 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -57,6 +57,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, transient int rotation; transient boolean enabled = true; transient float enabledControlTime; + transient String lastAccessed; PowerModule power; ItemModule items; @@ -879,6 +880,10 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, //null is of type void.class; anonymous classes use their superclass. Class type = value == null ? void.class : value.getClass().isAnonymousClass() ? value.getClass().getSuperclass() : value.getClass(); + if(builder != null && builder.isPlayer()){ + lastAccessed = builder.getPlayer().name; + } + if(block.configurations.containsKey(type)){ block.configurations.get(type).get(this, value); } @@ -1043,6 +1048,11 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, } } + if(net.active() && lastAccessed != null){ + table.row(); + table.add(Core.bundle.format("lastaccessed", lastAccessed)).growX().wrap().left(); + } + table.marginBottom(-5); } } diff --git a/core/src/mindustry/entities/comp/PayloadComp.java b/core/src/mindustry/entities/comp/PayloadComp.java index a27c7721be..ac1f4fa323 100644 --- a/core/src/mindustry/entities/comp/PayloadComp.java +++ b/core/src/mindustry/entities/comp/PayloadComp.java @@ -86,10 +86,10 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{ return true; } - if(payload instanceof BuildPayload){ - return dropBlock((BuildPayload)payload); - }else if(payload instanceof UnitPayload){ - return dropUnit((UnitPayload)payload); + if(payload instanceof BuildPayload b){ + return dropBlock(b); + }else if(payload instanceof UnitPayload p){ + return dropUnit(p); } return false; } @@ -126,6 +126,8 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{ int rot = (int)((rotation + 45f) / 90f) % 4; payload.place(on, rot); + if(isPlayer()) payload.build.lastAccessed = getPlayer().name; + Fx.unitDrop.at(tile); Fx.placeBlock.at(on.drawx(), on.drawy(), on.block().size); return true; diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java index 81fb2ff883..eebe40e15b 100644 --- a/core/src/mindustry/input/InputHandler.java +++ b/core/src/mindustry/input/InputHandler.java @@ -10,7 +10,6 @@ import arc.math.*; import arc.math.geom.*; import arc.scene.*; import arc.scene.event.*; -import arc.scene.ui.*; import arc.scene.ui.layout.*; import arc.struct.*; import arc.util.*; @@ -257,7 +256,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ } @Remote(targets = Loc.both, called = Loc.server, forward = true, unreliable = true) - public static void rotateBlock(Player player, Building tile, boolean direction){ + public static void rotateBlock(@Nullable Player player, Building tile, boolean direction){ if(tile == null) return; if(net.server() && (!Units.canInteract(player, tile) || @@ -265,6 +264,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ throw new ValidateException(player, "Player cannot rotate a block."); } + if(player != null) tile.lastAccessed = player.name; tile.rotation = Mathf.mod(tile.rotation + Mathf.sign(direction), 4); tile.updateProximity(); tile.noSleep(); diff --git a/core/src/mindustry/world/blocks/ConstructBlock.java b/core/src/mindustry/world/blocks/ConstructBlock.java index 8bd9a77c47..304ef07afa 100644 --- a/core/src/mindustry/world/blocks/ConstructBlock.java +++ b/core/src/mindustry/world/blocks/ConstructBlock.java @@ -58,7 +58,7 @@ public class ConstructBlock extends Block{ } @Remote(called = Loc.server) - public static void constructFinish(Tile tile, Block block, Unit builder, byte rotation, Team team, Object config){ + public static void constructFinish(Tile tile, Block block, @Nullable Unit builder, byte rotation, Team team, Object config){ if(tile == null) return; float healthf = tile.build == null ? 1f : tile.build.healthf(); @@ -76,6 +76,10 @@ public class ConstructBlock extends Block{ if(prev != null && prev.size > 0){ tile.build.overwrote(prev); } + + if(builder != null && builder.isPlayer()){ + tile.build.lastAccessed = builder.getPlayer().name; + } } //last builder was this local client player, call placed() From f12379ee07d1aefcb38170815d1fbeecea0591b4 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 11 Oct 2020 11:55:45 -0400 Subject: [PATCH 28/41] Fixed #2910 --- core/src/mindustry/type/Sector.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/src/mindustry/type/Sector.java b/core/src/mindustry/type/Sector.java index 21152cc954..4c1df28945 100644 --- a/core/src/mindustry/type/Sector.java +++ b/core/src/mindustry/type/Sector.java @@ -8,6 +8,7 @@ import arc.util.*; import mindustry.*; import mindustry.game.Saves.*; import mindustry.graphics.g3d.PlanetGrid.*; +import mindustry.world.modules.*; import static mindustry.Vars.*; @@ -151,7 +152,9 @@ public class Sector{ public void addItems(ItemSeq items){ if(isBeingPlayed()){ if(state.rules.defaultTeam.core() != null){ - state.rules.defaultTeam.items().add(items); + ItemModule storage = state.rules.defaultTeam.items(); + int cap = state.rules.defaultTeam.core().storageCapacity; + items.each((item, amount) -> storage.add(item, Math.min(cap - storage.get(item), amount))); } }else{ ItemSeq recv = getExtraItems(); From ad2bda8ec1f21870b7eefa5fe1f3ee0c86f2a54a Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 11 Oct 2020 13:33:02 -0400 Subject: [PATCH 29/41] Better sector gen --- core/src/mindustry/core/Logic.java | 2 ++ .../maps/planet/SerpuloPlanetGenerator.java | 27 +++++++++++++++---- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/core/src/mindustry/core/Logic.java b/core/src/mindustry/core/Logic.java index 31dee47410..0b79c97528 100644 --- a/core/src/mindustry/core/Logic.java +++ b/core/src/mindustry/core/Logic.java @@ -88,6 +88,8 @@ public class Logic implements ApplicationListener{ if(state.isCampaign()){ long seconds = state.rules.sector.getSecondsPassed(); CoreBuild core = state.rules.defaultTeam.core(); + //THE WAVES NEVER END + state.rules.waves = true; //apply fractional damage based on how many turns have passed for this sector float turnsPassed = seconds / (turnDuration / 60f); diff --git a/core/src/mindustry/maps/planet/SerpuloPlanetGenerator.java b/core/src/mindustry/maps/planet/SerpuloPlanetGenerator.java index 781bbdb7b5..fab208fd05 100644 --- a/core/src/mindustry/maps/planet/SerpuloPlanetGenerator.java +++ b/core/src/mindustry/maps/planet/SerpuloPlanetGenerator.java @@ -252,10 +252,6 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{ } }); - for(Room espawn : enemies){ - tiles.getn(espawn.x, espawn.y).setOverlay(Blocks.spawn); - } - trimDark(); median(2); @@ -273,7 +269,7 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{ //tar if(floor == Blocks.darksand){ if(Math.abs(0.5f - noise(x - 40, y, 2, 0.7, 80)) > 0.25f && - Math.abs(0.5f - noise(x, y + sector.id*10, 1, 1, 60)) > 0.41f){ + Math.abs(0.5f - noise(x, y + sector.id*10, 1, 1, 60)) > 0.41f && !(enemies.contains(r -> Mathf.within(x, y, r.x, r.y, 15)))){ floor = Blocks.tar; ore = Blocks.air; } @@ -298,6 +294,23 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{ } } + if(rand.chance(0.0075)){ + //random spore trees + boolean any = false; + boolean all = true; + for(Point2 p : Geometry.d4){ + Tile other = tiles.get(x + p.x, y + p.y); + if(other != null && other.block() == Blocks.air){ + any = true; + }else{ + all = false; + } + } + if(any && ((block == Blocks.snowWall || block == Blocks.iceWall) || (all && block == Blocks.air && floor == Blocks.snow && rand.chance(0.03)))){ + block = rand.chance(0.5) ? Blocks.whiteTree : Blocks.whiteTreeDead; + } + } + //random stuff dec: { for(int i = 0; i < 4; i++){ @@ -392,6 +405,10 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{ Schematics.placeLaunchLoadout(spawn.x, spawn.y); + for(Room espawn : enemies){ + tiles.getn(espawn.x, espawn.y).setOverlay(Blocks.spawn); + } + if(sector.hasEnemyBase()){ basegen.generate(tiles, enemies.map(r -> tiles.getn(r.x, r.y)), tiles.get(spawn.x, spawn.y), state.rules.waveTeam, sector, difficulty); From 4f258b54c535cf2df5478757a1b070bdf7fcdf86 Mon Sep 17 00:00:00 2001 From: Summet Date: Sun, 11 Oct 2020 20:47:04 +0300 Subject: [PATCH 30/41] Fix Vars.loops declaration --- core/src/mindustry/Vars.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/mindustry/Vars.java b/core/src/mindustry/Vars.java index 5d25f77cbf..37ba22d3cb 100644 --- a/core/src/mindustry/Vars.java +++ b/core/src/mindustry/Vars.java @@ -184,7 +184,7 @@ public class Vars implements Loadable{ public static GameState state; public static EntityCollisions collisions; public static DefaultWaves defaultWaves; - public static mindustry.audio.LoopControl loops; + public static LoopControl loops; public static Platform platform = new Platform(){}; public static Mods mods; public static Schematics schematics; From af54de894cd7dcfdf5fdeb8b0dbf5074facfb301 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 11 Oct 2020 14:05:16 -0400 Subject: [PATCH 31/41] Balancing / LogicAI sync --- core/src/mindustry/ai/types/LogicAI.java | 1 + core/src/mindustry/content/Blocks.java | 8 ++++---- core/src/mindustry/core/Logic.java | 2 +- core/src/mindustry/io/TypeIO.java | 24 ++++++++++++++++++++---- 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/core/src/mindustry/ai/types/LogicAI.java b/core/src/mindustry/ai/types/LogicAI.java index df856d6688..a7b606b932 100644 --- a/core/src/mindustry/ai/types/LogicAI.java +++ b/core/src/mindustry/ai/types/LogicAI.java @@ -21,6 +21,7 @@ public class LogicAI extends AIController{ public LUnitControl control = LUnitControl.stop; public float moveX, moveY, moveRad; public float itemTimer, payTimer, controlTimer = logicControlTimeout, targetTimer; + @Nullable public Building controller; public BuildPlan plan = new BuildPlan(); diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 51412a7ed2..149e2ed6d2 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -702,7 +702,7 @@ public class Blocks implements ContentList{ drawer = new DrawAnimation(); consumes.item(Items.sporePod, 1); - consumes.power(0.60f); + consumes.power(0.7f); }}; pulverizer = new GenericCrafter("pulverizer"){{ @@ -727,7 +727,7 @@ public class Blocks implements ContentList{ hasPower = hasItems = hasLiquids = true; consumes.liquid(Liquids.oil, 0.1f); - consumes.power(0.5f); + consumes.power(0.7f); }}; incinerator = new Incinerator("incinerator"){{ @@ -1287,7 +1287,7 @@ public class Blocks implements ContentList{ }}; cultivator = new Cultivator("cultivator"){{ - requirements(Category.production, with(Items.copper, 10, Items.lead, 25, Items.silicon, 10)); + requirements(Category.production, with(Items.copper, 25, Items.lead, 25, Items.silicon, 10)); outputItem = new ItemStack(Items.sporePod, 1); craftTime = 140; size = 2; @@ -1295,7 +1295,7 @@ public class Blocks implements ContentList{ hasPower = true; hasItems = true; - consumes.power(0.80f); + consumes.power(0.9f); consumes.liquid(Liquids.water, 0.2f); }}; diff --git a/core/src/mindustry/core/Logic.java b/core/src/mindustry/core/Logic.java index 0b79c97528..df536552df 100644 --- a/core/src/mindustry/core/Logic.java +++ b/core/src/mindustry/core/Logic.java @@ -92,7 +92,7 @@ public class Logic implements ApplicationListener{ state.rules.waves = true; //apply fractional damage based on how many turns have passed for this sector - float turnsPassed = seconds / (turnDuration / 60f); + //float turnsPassed = seconds / (turnDuration / 60f); //TODO sector damage disabled for now //if(state.rules.sector.hasWaves() && turnsPassed > 0 && state.rules.sector.hasBase()){ diff --git a/core/src/mindustry/io/TypeIO.java b/core/src/mindustry/io/TypeIO.java index 066ddc0efe..669cd65d53 100644 --- a/core/src/mindustry/io/TypeIO.java +++ b/core/src/mindustry/io/TypeIO.java @@ -290,12 +290,15 @@ public class TypeIO{ public static void writeController(Writes write, UnitController control){ //no real unit controller state is written, only the type - if(control instanceof Player){ + if(control instanceof Player p){ write.b(0); - write.i(((Player)control).id); - }else if(control instanceof FormationAI){ + write.i(p.id); + }else if(control instanceof FormationAI form){ write.b(1); - write.i(((FormationAI)control).leader.id); + write.i(form.leader.id); + }else if(control instanceof LogicAI logic && logic.controller != null){ + write.b(3); + write.i(logic.controller.pos()); }else{ write.b(2); } @@ -312,6 +315,19 @@ public class TypeIO{ }else if(type == 1){ //formation controller int id = read.i(); return prev instanceof FormationAI ? prev : new FormationAI(Groups.unit.getByID(id), null); + }else if(type == 3){ + int pos = read.i(); + if(prev instanceof LogicAI pai){ + pai.controller = world.build(pos); + return pai; + }else{ + //create new AI for assignment + LogicAI out = new LogicAI(); + //instantly time out when updated. + out.controlTimer = LogicAI.logicControlTimeout; + out.controller = world.build(pos); + return out; + } }else{ //there are two cases here: //1: prev controller was not a player, carry on From f1ec26f82ba15c9d09bc2d5b9fd7607b04bb1882 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 11 Oct 2020 14:10:55 -0400 Subject: [PATCH 32/41] Correct logic control position rendering --- core/src/mindustry/graphics/OverlayRenderer.java | 9 +++++++++ .../mindustry/world/blocks/logic/LogicBlock.java | 16 ---------------- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/core/src/mindustry/graphics/OverlayRenderer.java b/core/src/mindustry/graphics/OverlayRenderer.java index ea988e5e78..e796b0b168 100644 --- a/core/src/mindustry/graphics/OverlayRenderer.java +++ b/core/src/mindustry/graphics/OverlayRenderer.java @@ -7,6 +7,7 @@ import arc.math.*; import arc.math.geom.*; import arc.util.*; import mindustry.*; +import mindustry.ai.types.*; import mindustry.gen.*; import mindustry.input.*; import mindustry.ui.*; @@ -151,6 +152,14 @@ public class OverlayRenderer{ input.drawOverSelect(); + if(ui.hudfrag.blockfrag.hover() instanceof Unit unit && unit.controller() instanceof LogicAI ai && ai.controller instanceof Building build){ + Draw.z(Layer.overlayUI); + Drawf.square(build.x, build.y, build.block.size * tilesize/2f + 2f); + if(!unit.within(build, unit.hitSize * 2f)){ + Drawf.arrow(unit.x, unit.y, build.x, build.y, unit.hitSize *2f, 4f); + } + } + //draw selection overlay when dropping item if(input.isDroppingItem()){ Vec2 v = Core.input.mouseWorld(input.getMouseX(), input.getMouseY()); diff --git a/core/src/mindustry/world/blocks/logic/LogicBlock.java b/core/src/mindustry/world/blocks/logic/LogicBlock.java index f3962a5448..aecf5d4149 100644 --- a/core/src/mindustry/world/blocks/logic/LogicBlock.java +++ b/core/src/mindustry/world/blocks/logic/LogicBlock.java @@ -1,7 +1,6 @@ package mindustry.world.blocks.logic; import arc.func.*; -import arc.graphics.g2d.*; import arc.math.geom.*; import arc.scene.ui.layout.*; import arc.struct.Bits; @@ -9,7 +8,6 @@ import arc.struct.*; import arc.util.*; import arc.util.io.*; import mindustry.*; -import mindustry.ai.types.*; import mindustry.gen.*; import mindustry.graphics.*; import mindustry.io.*; @@ -425,7 +423,6 @@ public class LogicBlock extends Block{ @Override public void buildConfiguration(Table table){ - table.button(Icon.pencil, Styles.clearTransi, () -> { Vars.ui.logic.show(code, code -> { configure(compress(code, relativeConnections())); @@ -433,19 +430,6 @@ public class LogicBlock extends Block{ }).size(40); } - @Override - public void draw(){ - super.draw(); - - if(ui.hudfrag.blockfrag.hover() instanceof Unit unit && unit.controller() instanceof LogicAI ai && ai.controller == this){ - Draw.z(Layer.overlayUI); - Drawf.square(x, y, size * tilesize/2f + 2f); - if(!unit.within(this, unit.hitSize * 2f)){ - Drawf.arrow(unit.x, unit.y, x, y, unit.hitSize *2f, 4f); - } - } - } - @Override public boolean onConfigureTileTapped(Building other){ if(this == other){ From 2f6f205dc77b402d1c5d4056f2ec2c8ef8734edd Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 11 Oct 2020 14:20:53 -0400 Subject: [PATCH 33/41] Better builder detection for ConstructBlock --- .../src/mindustry/graphics/OverlayRenderer.java | 1 - .../mindustry/world/blocks/ConstructBlock.java | 17 +++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/core/src/mindustry/graphics/OverlayRenderer.java b/core/src/mindustry/graphics/OverlayRenderer.java index e796b0b168..19569ed1a3 100644 --- a/core/src/mindustry/graphics/OverlayRenderer.java +++ b/core/src/mindustry/graphics/OverlayRenderer.java @@ -153,7 +153,6 @@ public class OverlayRenderer{ input.drawOverSelect(); if(ui.hudfrag.blockfrag.hover() instanceof Unit unit && unit.controller() instanceof LogicAI ai && ai.controller instanceof Building build){ - Draw.z(Layer.overlayUI); Drawf.square(build.x, build.y, build.block.size * tilesize/2f + 2f); if(!unit.within(build, unit.hitSize * 2f)){ Drawf.arrow(unit.x, unit.y, build.x, build.y, unit.hitSize *2f, 4f); diff --git a/core/src/mindustry/world/blocks/ConstructBlock.java b/core/src/mindustry/world/blocks/ConstructBlock.java index 304ef07afa..c228397a32 100644 --- a/core/src/mindustry/world/blocks/ConstructBlock.java +++ b/core/src/mindustry/world/blocks/ConstructBlock.java @@ -146,6 +146,9 @@ public class ConstructBlock extends Block{ public Block previous; public Object lastConfig; + @Nullable + public Unit lastBuilder; + private float[] accumulator; private float[] totalAccumulator; @@ -218,6 +221,10 @@ public class ConstructBlock extends Block{ return; } + if(builder.isPlayer()){ + lastBuilder = builder; + } + lastConfig = config; if(cblock.requirements.length != accumulator.length || totalAccumulator.length != cblock.requirements.length){ @@ -237,13 +244,18 @@ public class ConstructBlock extends Block{ progress = Mathf.clamp(progress + maxProgress); if(progress >= 1f || state.rules.infiniteResources){ - constructed(tile, cblock, builder, (byte)rotation, builder.team, config); + if(lastBuilder == null) lastBuilder = builder; + constructed(tile, cblock, lastBuilder, (byte)rotation, builder.team, config); } } public void deconstruct(Unit builder, @Nullable Building core, float amount){ float deconstructMultiplier = state.rules.deconstructRefundMultiplier; + if(builder.isPlayer()){ + lastBuilder = builder; + } + if(cblock != null){ ItemStack[] requirements = cblock.requirements; if(requirements.length != accumulator.length || totalAccumulator.length != requirements.length){ @@ -275,7 +287,8 @@ public class ConstructBlock extends Block{ progress = Mathf.clamp(progress - amount); if(progress <= 0 || state.rules.infiniteResources){ - Call.deconstructFinish(tile, this.cblock == null ? previous : this.cblock, builder); + if(lastBuilder == null) lastBuilder = builder; + Call.deconstructFinish(tile, this.cblock == null ? previous : this.cblock, lastBuilder); } } From ee50995dde9b50cb20ec1bcfbf392ae20eb5bce8 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 11 Oct 2020 14:54:05 -0400 Subject: [PATCH 34/41] Removed "sector attacked" message --- core/src/mindustry/ai/WaveSpawner.java | 8 ++++++-- .../src/mindustry/entities/comp/BuilderComp.java | 1 - core/src/mindustry/ui/fragments/HudFragment.java | 14 -------------- .../world/blocks/storage/CoreBlock.java | 16 ++++++++++++++++ 4 files changed, 22 insertions(+), 17 deletions(-) diff --git a/core/src/mindustry/ai/WaveSpawner.java b/core/src/mindustry/ai/WaveSpawner.java index 417909a92b..9cecf32ac1 100644 --- a/core/src/mindustry/ai/WaveSpawner.java +++ b/core/src/mindustry/ai/WaveSpawner.java @@ -77,14 +77,18 @@ public class WaveSpawner{ eachGroundSpawn((spawnX, spawnY, doShockwave) -> { if(doShockwave){ - Time.run(20f, () -> Fx.spawnShockwave.at(spawnX, spawnY, state.rules.dropZoneRadius)); - Time.run(40f, () -> Damage.damage(state.rules.waveTeam, spawnX, spawnY, state.rules.dropZoneRadius, 99999999f, true)); + doShockwave(spawnX, spawnY); } }); Time.runTask(121f, () -> spawning = false); } + public void doShockwave(float x, float y){ + Time.run(20f, () -> Fx.spawnShockwave.at(x, y, state.rules.dropZoneRadius)); + Time.run(40f, () -> Damage.damage(state.rules.waveTeam, x, y, state.rules.dropZoneRadius, 99999999f, true)); + } + private void eachGroundSpawn(SpawnConsumer cons){ for(Tile spawn : spawns){ cons.accept(spawn.worldx(), spawn.worldy(), true); diff --git a/core/src/mindustry/entities/comp/BuilderComp.java b/core/src/mindustry/entities/comp/BuilderComp.java index d57b1b5b6d..0aafd4d0c0 100644 --- a/core/src/mindustry/entities/comp/BuilderComp.java +++ b/core/src/mindustry/entities/comp/BuilderComp.java @@ -116,7 +116,6 @@ abstract class BuilderComp implements Unitc{ current.progress = entity.progress; } - /** Draw all current build requests. Does not draw the beam effect, only the positions. */ void drawBuildRequests(){ diff --git a/core/src/mindustry/ui/fragments/HudFragment.java b/core/src/mindustry/ui/fragments/HudFragment.java index 4f289f9293..f56d507c4d 100644 --- a/core/src/mindustry/ui/fragments/HudFragment.java +++ b/core/src/mindustry/ui/fragments/HudFragment.java @@ -84,20 +84,6 @@ public class HudFragment extends Fragment{ coreItems.clear(); }); - Events.on(TurnEvent.class, e -> { - Seq attacked = universe.getAttacked(state.getSector().planet); - - if(attacked.any()){ - - //TODO localize - String text = attacked.size > 1 ? attacked.size + " sectors attacked." : "Sector " + attacked.first().id + " under attack."; - - showToast(Icon.warning, text); - } - - //ui.announce("[accent][[ Turn " + universe.turn() + " ]\n[scarlet]" + attackedSectors.size + "[lightgray] sector(s) attacked."); - }); - //paused table parent.fill(t -> { t.name = "paused"; diff --git a/core/src/mindustry/world/blocks/storage/CoreBlock.java b/core/src/mindustry/world/blocks/storage/CoreBlock.java index 8d656a95d2..bdb16eb674 100644 --- a/core/src/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/mindustry/world/blocks/storage/CoreBlock.java @@ -310,6 +310,22 @@ public class CoreBlock extends StorageBlock{ } } + @Override + public void onDestroyed(){ + super.onDestroyed(); + + if(state.isCampaign() && team == state.rules.waveTeam){ + //do not recache + world.setGenerating(true); + tile.setOverlay(Blocks.spawn); + world.setGenerating(false); + + if(!spawner.getSpawns().contains(tile)){ + spawner.getSpawns().add(tile); + } + spawner.doShockwave(x, y); + } + } @Override public void placed(){ From 7662174dc41c52fbfdb019633bf278fc9a56f5d4 Mon Sep 17 00:00:00 2001 From: MEEP of Faith Date: Sun, 11 Oct 2020 12:58:50 -0700 Subject: [PATCH 35/41] oki doki --- core/src/mindustry/world/blocks/defense/turrets/Turret.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/mindustry/world/blocks/defense/turrets/Turret.java b/core/src/mindustry/world/blocks/defense/turrets/Turret.java index 378b90da4e..703833594a 100644 --- a/core/src/mindustry/world/blocks/defense/turrets/Turret.java +++ b/core/src/mindustry/world/blocks/defense/turrets/Turret.java @@ -432,7 +432,7 @@ public abstract class Turret extends Block{ fshootEffect.at(x + tr.x, y + tr.y, rotation); fsmokeEffect.at(x + tr.x, y + tr.y, rotation); - shootSound.at(x + tr.x, y + tr.y, 1); + shootSound.at(x + tr.x, y + tr.y, Mathf.random(0.9f, 1.1f)); if(shootShake > 0){ Effect.shake(shootShake, shootShake, this); From 6807b589a333a4204e542f811dfdf2cc82d0a8d4 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 11 Oct 2020 19:10:33 -0400 Subject: [PATCH 36/41] Logic unit control tweaks --- core/src/mindustry/logic/LAssembler.java | 3 +++ core/src/mindustry/logic/LExecutor.java | 14 ++++++++++++-- core/src/mindustry/logic/LLocate.java | 3 ++- core/src/mindustry/logic/LStatements.java | 2 +- core/src/mindustry/logic/LUnitControl.java | 2 +- 5 files changed, 19 insertions(+), 5 deletions(-) diff --git a/core/src/mindustry/logic/LAssembler.java b/core/src/mindustry/logic/LAssembler.java index e355416427..4f72d121aa 100644 --- a/core/src/mindustry/logic/LAssembler.java +++ b/core/src/mindustry/logic/LAssembler.java @@ -52,6 +52,9 @@ public class LAssembler{ } } + //used as a special value for any environmental solid block + putConst("@solid", Blocks.stoneWall); + putConst("@air", Blocks.air); for(UnitType type : Vars.content.units()){ diff --git a/core/src/mindustry/logic/LExecutor.java b/core/src/mindustry/logic/LExecutor.java index 93c5263a9b..3bcfaf46ee 100644 --- a/core/src/mindustry/logic/LExecutor.java +++ b/core/src/mindustry/logic/LExecutor.java @@ -6,6 +6,7 @@ import arc.util.*; import arc.util.noise.*; import mindustry.*; import mindustry.ai.types.*; +import mindustry.content.*; import mindustry.ctype.*; import mindustry.entities.*; import mindustry.game.*; @@ -251,6 +252,11 @@ public class LExecutor{ case spawn -> { res = Geometry.findClosest(unit.x, unit.y, Vars.spawner.getSpawns()); } + case damaged -> { + Building b = Units.findDamagedTile(unit.team, unit.x, unit.y); + res = b == null ? null : b.tile; + build = true; + } } if(res != null && (!build || res.build != null)){ @@ -435,12 +441,16 @@ public class LExecutor{ } case getBlock -> { float x = exec.numf(p1), y = exec.numf(p2); - if(unit.within(x, y, unit.range())){ + float range = Math.max(unit.range(), buildingRange); + if(!unit.within(x, y, range)){ exec.setobj(p3, null); + exec.setnum(p4, 0); }else{ Tile tile = world.tileWorld(x, y); - Block block = tile == null || !tile.synthetic() ? null : tile.block(); + //any environmental solid block is returned as StoneWall, aka "@solid" + Block block = tile == null ? null : !tile.synthetic() ? (tile.solid() ? Blocks.stoneWall : Blocks.air) : tile.block(); exec.setobj(p3, block); + exec.setnum(p4, tile != null && tile.build != null ? tile.build.rotation : 0); } } case itemDrop -> { diff --git a/core/src/mindustry/logic/LLocate.java b/core/src/mindustry/logic/LLocate.java index 679136e74f..84da2321f9 100644 --- a/core/src/mindustry/logic/LLocate.java +++ b/core/src/mindustry/logic/LLocate.java @@ -3,7 +3,8 @@ package mindustry.logic; public enum LLocate{ ore, building, - spawn; + spawn, + damaged; public static final LLocate[] all = values(); } diff --git a/core/src/mindustry/logic/LStatements.java b/core/src/mindustry/logic/LStatements.java index a96adaf9d9..ba4d31e9a1 100644 --- a/core/src/mindustry/logic/LStatements.java +++ b/core/src/mindustry/logic/LStatements.java @@ -889,7 +889,7 @@ public class LStatements{ table.row(); } - case spawn -> { + case spawn, damaged -> { table.row(); } } diff --git a/core/src/mindustry/logic/LUnitControl.java b/core/src/mindustry/logic/LUnitControl.java index 879578e59b..2166b00690 100644 --- a/core/src/mindustry/logic/LUnitControl.java +++ b/core/src/mindustry/logic/LUnitControl.java @@ -15,7 +15,7 @@ public enum LUnitControl{ mine("x", "y"), flag("value"), build("x", "y", "block", "rotation"), - getBlock("x", "y", "result"), + getBlock("x", "y", "result", "resRot"), within("x", "y", "radius", "result"); public final String[] params; From 9edec3c7ab6eaa7615c658125b747b121c97999c Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 11 Oct 2020 19:14:16 -0400 Subject: [PATCH 37/41] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6b1dfd72ac..11dbe8cd1e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ script: - git clone --depth=1 --branch=master https://github.com/Anuken/MindustryBuilds ../MindustryBuilds - cd ../MindustryBuilds - echo ${TRAVIS_TAG} -- if [ -n "$TRAVIS_TAG" ]; then echo versionName=5-fdroid-${TRAVIS_TAG:1}$'\n'versionCode=${TRAVIS_TAG:1} > version_fdroid.txt; git add .; git commit -m "Updating to build ${TRAVIS_TAG}"; fi +- if [ -n "$TRAVIS_TAG" ]; then echo versionName=6-fdroid-${TRAVIS_TAG:1}$'\n'versionCode=${TRAVIS_TAG:1} > version_fdroid.txt; git add .; git commit -m "Updating to build ${TRAVIS_TAG}"; fi - git tag ${TRAVIS_BUILD_NUMBER} - git config --global user.name "Build Uploader" - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then git push https://Anuken:${GH_PUSH_TOKEN}@github.com/Anuken/MindustryBuilds ${TRAVIS_BUILD_NUMBER}; git push https://Anuken:${GH_PUSH_TOKEN}@github.com/Anuken/MindustryBuilds; fi From 08629bb7f71b93e6022c81b22edc23a7d6a41fd2 Mon Sep 17 00:00:00 2001 From: Wiki Updater <57631841+Catchears@users.noreply.github.com> Date: Mon, 12 Oct 2020 10:49:41 +0200 Subject: [PATCH 38/41] add bundle entry for dacit boulder --- core/assets/bundles/bundle.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 70d7430557..51c8ac2485 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -994,6 +994,7 @@ block.darksand-water.name = Dark Sand Water block.char.name = Char block.dacite.name = Dacite block.dacite-wall.name = Dacite Wall +block.dacite-boulder.name = Dacite Boulder block.ice-snow.name = Ice Snow block.stone-wall.name = Stone Wall block.ice-wall.name = Ice Wall From 378e81cd90724961b29241c94848b7bc9a6f64b4 Mon Sep 17 00:00:00 2001 From: Anuken Date: Mon, 12 Oct 2020 10:06:34 -0400 Subject: [PATCH 39/41] Fixed #2917 --- core/assets/bundles/bundle.properties | 2 +- core/src/mindustry/content/UnitTypes.java | 6 +++--- core/src/mindustry/ctype/UnlockableContent.java | 2 +- core/src/mindustry/game/DefaultWaves.java | 8 ++++++++ core/src/mindustry/ui/dialogs/ResearchDialog.java | 5 +++-- 5 files changed, 16 insertions(+), 7 deletions(-) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 70d7430557..ea6f0dda6b 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -20,7 +20,7 @@ gameover = Game Over gameover.pvp = The[accent] {0}[] team is victorious! highscore = [accent]New highscore! copied = Copied. -indev.popup = [accent]v6[] is currently in [accent]alpha[].\n[lightgray]This means:[]\n[scarlet]- The campaign is completely unfinished[]\n- Content is missing\n - Most [scarlet]Unit AI[] does not work properly\n- Many units are unfinished\n- Everything you see is subject to change or removal.\n\nReport bugs or crashes on [accent]Github[]. +indev.popup = [accent]v6[] is currently in [accent]alpha[].\n[lightgray]This means:[]\n[scarlet]- The campaign is completely unfinished[]\n- SFX and music are unfinished/missing\n- Everything you see is subject to change or removal.\n\nReport bugs or crashes on [accent]Github[]. indev.notready = This part of the game isn't ready yet load.sound = Sounds diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index f98676f156..7474168ef6 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -1544,7 +1544,7 @@ public class UnitTypes implements ContentList{ xRand = 8f; shotDelay = 1f; - bullet = new MissileBulletType(4.2f, 25){{ + bullet = new MissileBulletType(4.2f, 30){{ homingPower = 0.12f; width = 8f; height = 8f; @@ -1552,8 +1552,8 @@ public class UnitTypes implements ContentList{ drag = -0.003f; homingRange = 80f; keepVelocity = false; - splashDamageRadius = 25f; - splashDamage = 25f; + splashDamageRadius = 30f; + splashDamage = 35f; lifetime = 56f; trailColor = Pal.bulletYellowBack; backColor = Pal.bulletYellowBack; diff --git a/core/src/mindustry/ctype/UnlockableContent.java b/core/src/mindustry/ctype/UnlockableContent.java index 56e9c31146..f6e6d0a2dc 100644 --- a/core/src/mindustry/ctype/UnlockableContent.java +++ b/core/src/mindustry/ctype/UnlockableContent.java @@ -22,7 +22,7 @@ public abstract class UnlockableContent extends MappableContent{ /** Whether this content is always unlocked in the tech tree. */ public boolean alwaysUnlocked = false; /** Icons by Cicon ID.*/ - protected TextureRegion[] cicons = new TextureRegion[mindustry.ui.Cicon.all.length]; + protected TextureRegion[] cicons = new TextureRegion[Cicon.all.length]; /** Unlock state. Loaded from settings. Do not modify outside of the constructor. */ protected boolean unlocked; diff --git a/core/src/mindustry/game/DefaultWaves.java b/core/src/mindustry/game/DefaultWaves.java index e21b13ca8c..bc03b29e0f 100644 --- a/core/src/mindustry/game/DefaultWaves.java +++ b/core/src/mindustry/game/DefaultWaves.java @@ -339,6 +339,14 @@ public class DefaultWaves{ shieldScaling = shieldsPerWave; }}); + //shift back waves on higher difficulty for a harder start + int shift = Math.max((int)(difficulty * 15 - 5), 0); + + for(SpawnGroup group : out){ + group.begin -= shift; + group.end -= shift; + } + return out; } } diff --git a/core/src/mindustry/ui/dialogs/ResearchDialog.java b/core/src/mindustry/ui/dialogs/ResearchDialog.java index b1dbea2528..9c5e6fd3ed 100644 --- a/core/src/mindustry/ui/dialogs/ResearchDialog.java +++ b/core/src/mindustry/ui/dialogs/ResearchDialog.java @@ -400,7 +400,8 @@ public class ResearchDialog extends BaseDialog{ } } - return false; + //can always spend when locked + return node.content.locked(); } void spend(TechNode node){ @@ -414,7 +415,7 @@ public class ResearchDialog extends BaseDialog{ ItemStack completed = node.finishedRequirements[i]; //amount actually taken from inventory - int used = Math.min(req.amount - completed.amount, items.get(req.item)); + int used = Math.max(Math.min(req.amount - completed.amount, items.get(req.item)), 0); items.remove(req.item, used); completed.amount += used; From 876534bd26accd13a1e12100321a08c19426853a Mon Sep 17 00:00:00 2001 From: Anuken Date: Mon, 12 Oct 2020 14:33:22 -0400 Subject: [PATCH 40/41] Wave balancing & AI tweaks --- core/src/mindustry/ai/types/BuilderAI.java | 24 +++++++++++++++-- core/src/mindustry/ai/types/RepairAI.java | 27 +++++++++++++------ core/src/mindustry/content/UnitTypes.java | 2 +- .../entities/units/AIController.java | 17 ++++++++++++ core/src/mindustry/game/DefaultWaves.java | 25 ++++++++++++----- 5 files changed, 78 insertions(+), 17 deletions(-) diff --git a/core/src/mindustry/ai/types/BuilderAI.java b/core/src/mindustry/ai/types/BuilderAI.java index 1e1875e176..8e8c74f986 100644 --- a/core/src/mindustry/ai/types/BuilderAI.java +++ b/core/src/mindustry/ai/types/BuilderAI.java @@ -17,13 +17,17 @@ public class BuilderAI extends AIController{ @Nullable Builderc following; @Override - public void updateUnit(){ + public void updateMovement(){ Builderc builder = (Builderc)unit; if(builder.moving()){ builder.lookAt(builder.vel().angle()); } + if(target != null && shouldShoot()){ + unit.lookAt(target); + } + builder.updateBuilding(true); if(following != null){ @@ -95,13 +99,29 @@ public class BuilderAI extends AIController{ }else if(Build.validPlace(content.block(block.block), unit.team(), block.x, block.y, block.rotation)){ //it's valid. //add build request. builder.addBuild(new BuildPlan(block.x, block.y, block.rotation, content.block(block.block), block.config)); + //shift build plan to tail so next unit builds something else. + blocks.addLast(blocks.removeFirst()); }else{ //shift head of queue to tail, try something else next time blocks.removeFirst(); blocks.addLast(block); } } - } } + + @Override + public AIController fallback(){ + return unit.type().flying ? new FlyingAI() : new GroundAI(); + } + + @Override + public boolean useFallback(){ + return state.rules.waves && unit.team == state.rules.waveTeam && !unit.team.rules().ai; + } + + @Override + public boolean shouldShoot(){ + return !((Builderc)unit).isBuilding(); + } } diff --git a/core/src/mindustry/ai/types/RepairAI.java b/core/src/mindustry/ai/types/RepairAI.java index 84baf1c555..5f021ae828 100644 --- a/core/src/mindustry/ai/types/RepairAI.java +++ b/core/src/mindustry/ai/types/RepairAI.java @@ -2,27 +2,33 @@ package mindustry.ai.types; import mindustry.entities.*; import mindustry.entities.units.*; +import mindustry.gen.*; import mindustry.world.blocks.ConstructBlock.*; -//note that repair AI doesn't attack anything even if it theoretically can public class RepairAI extends AIController{ @Override protected void updateMovement(){ - boolean shoot = false; - - if(target != null){ - if(!target.within(unit, unit.type().range * 0.8f)){ - moveTo(target, unit.type().range * 0.8f); - } + if(target instanceof Building){ + boolean shoot = false; if(target.within(unit, unit.type().range)){ unit.aim(target); shoot = true; } + + unit.controlWeapons(shoot); + }else if(target == null){ + unit.controlWeapons(false); } - unit.controlWeapons(shoot); + if(target != null){ + if(!target.within(unit, unit.type().range * 0.65f)){ + moveTo(target, unit.type().range * 0.65f); + } + + unit.lookAt(target); + } } @Override @@ -30,5 +36,10 @@ public class RepairAI extends AIController{ target = Units.findDamagedTile(unit.team, unit.x, unit.y); if(target instanceof ConstructBuild) target = null; + + if(target == null){ + super.updateTargeting(); + } } + } diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index 7474168ef6..9a1b851118 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -1145,7 +1145,7 @@ public class UnitTypes implements ContentList{ speed = 1.9f; rotateSpeed = 15f; accel = 0.1f; - range = 70f; + range = 130f; health = 400; buildSpeed = 0.5f; engineOffset = 6.5f; diff --git a/core/src/mindustry/entities/units/AIController.java b/core/src/mindustry/entities/units/AIController.java index d235972212..b02fa5dc00 100644 --- a/core/src/mindustry/entities/units/AIController.java +++ b/core/src/mindustry/entities/units/AIController.java @@ -21,6 +21,7 @@ public class AIController implements UnitController{ protected Unit unit; protected Interval timer = new Interval(4); + protected AIController fallback; /** main target that is being faced */ protected Teamc target; @@ -34,11 +35,27 @@ public class AIController implements UnitController{ @Override public void updateUnit(){ + //use fallback AI when possible + if(useFallback() && (fallback != null || (fallback = fallback()) != null)){ + if(fallback.unit != unit) fallback.unit(unit); + fallback.updateUnit(); + return; + } + updateVisuals(); updateTargeting(); updateMovement(); } + @Nullable + protected AIController fallback(){ + return null; + } + + protected boolean useFallback(){ + return false; + } + protected UnitCommand command(){ return unit.team.data().command; } diff --git a/core/src/mindustry/game/DefaultWaves.java b/core/src/mindustry/game/DefaultWaves.java index bc03b29e0f..53a0bfa99c 100644 --- a/core/src/mindustry/game/DefaultWaves.java +++ b/core/src/mindustry/game/DefaultWaves.java @@ -119,6 +119,7 @@ public class DefaultWaves{ unitAmount = 2; unitScaling = 2; max = 20; + shieldScaling = 30; }}, new SpawnGroup(dagger){{ @@ -144,6 +145,7 @@ public class DefaultWaves{ unitAmount = 2; spacing = 2; unitScaling = 2; + shieldScaling = 20; }}, new SpawnGroup(flare){{ @@ -162,6 +164,7 @@ public class DefaultWaves{ unitScaling = 3; spacing = 5; max = 16; + shieldScaling = 30; }}, new SpawnGroup(nova){{ @@ -169,6 +172,7 @@ public class DefaultWaves{ unitAmount = 2; unitScaling = 3; spacing = 4; + shieldScaling = 20; }}, new SpawnGroup(atrax){{ @@ -192,15 +196,15 @@ public class DefaultWaves{ unitAmount = 1; unitScaling = 1; spacing = 40; - shieldScaling = 10f; + shieldScaling = 20f; }}, new SpawnGroup(antumbra){{ - begin = 131; + begin = 120; unitAmount = 1; unitScaling = 1; spacing = 40; - shieldScaling = 10f; + shieldScaling = 20f; }}, new SpawnGroup(vela){{ @@ -211,6 +215,15 @@ public class DefaultWaves{ shieldScaling = 20f; }}, + new SpawnGroup(corvus){{ + begin = 145; + unitAmount = 1; + unitScaling = 1; + spacing = 35; + shieldScaling = 30f; + shields = 100; + }}, + new SpawnGroup(horizon){{ begin = 90; unitAmount = 2; @@ -252,7 +265,7 @@ public class DefaultWaves{ //max reasonable wave, after which everything gets boring int cap = 200; - float shieldStart = 30, shieldsPerWave = 15 + difficulty*20f; + float shieldStart = 30, shieldsPerWave = 20 + difficulty*30f; Intc createProgression = start -> { //main sequence @@ -314,8 +327,8 @@ public class DefaultWaves{ step += (int)(Mathf.random(12, 25) * Mathf.lerp(1f, 0.4f, difficulty)); } - int bossWave = Mathf.random(30, 60); - int bossSpacing = Mathf.random(30, 50); + int bossWave = (int)(Mathf.random(30, 60) * Mathf.lerp(1f, 0.7f, difficulty)); + int bossSpacing = (int)(Mathf.random(25, 40) * Mathf.lerp(1f, 0.6f, difficulty)); //main boss progression out.add(new SpawnGroup(Structs.random(species)[4]){{ From 06877b457e692f024de3f32e939a9a29a8ed3aa2 Mon Sep 17 00:00:00 2001 From: Anuken Date: Mon, 12 Oct 2020 15:59:22 -0400 Subject: [PATCH 41/41] Rule selection fixes --- core/src/mindustry/maps/Map.java | 4 +++- .../maps/planet/SerpuloPlanetGenerator.java | 16 ++++++++-------- .../mindustry/ui/dialogs/CustomRulesDialog.java | 4 ++-- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/core/src/mindustry/maps/Map.java b/core/src/mindustry/maps/Map.java index edef90cea7..0fdc818139 100644 --- a/core/src/mindustry/maps/Map.java +++ b/core/src/mindustry/maps/Map.java @@ -98,7 +98,9 @@ public class Map implements Comparable, Publishable{ public Rules rules(Rules base){ try{ - Rules result = JsonIO.read(Rules.class, base, tags.get("rules", "{}")); + //this replacement is a MASSIVE hack but it fixes some incorrect overwriting of team-specific rules. + //may need to be tweaked later + Rules result = JsonIO.read(Rules.class, base, tags.get("rules", "{}").replace("teams:{2:{infiniteAmmo:true}},", "")); if(result.spawns.isEmpty()) result.spawns = Vars.defaultWaves.get(); return result; }catch(Exception e){ diff --git a/core/src/mindustry/maps/planet/SerpuloPlanetGenerator.java b/core/src/mindustry/maps/planet/SerpuloPlanetGenerator.java index fab208fd05..ee2f6b437c 100644 --- a/core/src/mindustry/maps/planet/SerpuloPlanetGenerator.java +++ b/core/src/mindustry/maps/planet/SerpuloPlanetGenerator.java @@ -145,7 +145,7 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{ float constraint = 1.3f; float radius = width / 2f / Mathf.sqrt3; int rooms = rand.random(2, 5); - Seq array = new Seq<>(); + Seq roomseq = new Seq<>(); for(int i = 0; i < rooms; i++){ Tmp.v1.trns(rand.random(360f), rand.random(radius / constraint)); @@ -153,7 +153,7 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{ float ry = (height/2f + Tmp.v1.y); float maxrad = radius - Tmp.v1.len(); float rrad = Math.min(rand.random(9f, maxrad / 2f), 30f); - array.add(new Room((int)rx, (int)ry, (int)rrad)); + roomseq.add(new Room((int)rx, (int)ry, (int)rrad)); } //check positions on the map to place the player spawn. this needs to be in the corner of the map @@ -182,13 +182,13 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{ } if(waterTiles <= 4 || (i + angleStep >= 360)){ - array.add(spawn = new Room(cx, cy, rand.random(8, 15))); + roomseq.add(spawn = new Room(cx, cy, rand.random(8, 15))); for(int j = 0; j < enemySpawns; j++){ float enemyOffset = rand.range(60f); Tmp.v1.set(cx - width/2, cy - height/2).rotate(180f + enemyOffset).add(width/2, height/2); Room espawn = new Room((int)Tmp.v1.x, (int)Tmp.v1.y, rand.random(8, 15)); - array.add(espawn); + roomseq.add(espawn); enemies.add(espawn); } @@ -196,16 +196,16 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{ } } - for(Room room : array){ + for(Room room : roomseq){ erase(room.x, room.y, room.radius); } int connections = rand.random(Math.max(rooms - 1, 1), rooms + 3); for(int i = 0; i < connections; i++){ - array.random(rand).connect(array.random(rand)); + roomseq.random(rand).connect(roomseq.random(rand)); } - for(Room room : array){ + for(Room room : roomseq){ spawn.connect(room); } @@ -269,7 +269,7 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{ //tar if(floor == Blocks.darksand){ if(Math.abs(0.5f - noise(x - 40, y, 2, 0.7, 80)) > 0.25f && - Math.abs(0.5f - noise(x, y + sector.id*10, 1, 1, 60)) > 0.41f && !(enemies.contains(r -> Mathf.within(x, y, r.x, r.y, 15)))){ + Math.abs(0.5f - noise(x, y + sector.id*10, 1, 1, 60)) > 0.41f && !(roomseq.contains(r -> Mathf.within(x, y, r.x, r.y, 15)))){ floor = Blocks.tar; ore = Blocks.air; } diff --git a/core/src/mindustry/ui/dialogs/CustomRulesDialog.java b/core/src/mindustry/ui/dialogs/CustomRulesDialog.java index e14629b594..42fac7be72 100644 --- a/core/src/mindustry/ui/dialogs/CustomRulesDialog.java +++ b/core/src/mindustry/ui/dialogs/CustomRulesDialog.java @@ -24,8 +24,8 @@ import static arc.util.Time.*; import static mindustry.Vars.*; public class CustomRulesDialog extends BaseDialog{ - private Table main; Rules rules; + private Table main; private Prov resetter; private LoadoutDialog loadoutDialog; private BaseDialog banDialog; @@ -166,7 +166,7 @@ public class CustomRulesDialog extends BaseDialog{ title("@rules.title.enemy"); check("@rules.attack", b -> rules.attackMode = b, () -> rules.attackMode); - check("@rules.buildai", b -> rules.waveTeam.rules().ai = b, () -> rules.waveTeam.rules().ai); + check("@rules.buildai", b -> rules.teams.get(rules.waveTeam).ai = rules.teams.get(rules.waveTeam).infiniteResources = b, () -> rules.teams.get(rules.waveTeam).ai); number("@rules.enemycorebuildradius", f -> rules.enemyCoreBuildRadius = f * tilesize, () -> Math.min(rules.enemyCoreBuildRadius / tilesize, 200)); title("@rules.title.environment");