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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 Szw@j8ztZ3T8P_trngjsUlh||s literal 11757 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 diff --git a/core/src/mindustry/Vars.java b/core/src/mindustry/Vars.java index be658a7a87..5d25f77cbf 100644 --- a/core/src/mindustry/Vars.java +++ b/core/src/mindustry/Vars.java @@ -85,7 +85,7 @@ public class Vars implements Loadable{ /** range for moving items for logic units */ public static final float logicItemTransferRange = 45f; /** duration of time between turns in ticks */ - public static final float turnDuration = 20 * Time.toMinutes; + public static final float turnDuration = 2 * Time.toMinutes; /** turns needed to destroy a sector completely */ public static final float sectorDestructionTurns = 2f; /** min armor fraction damage; e.g. 0.05 = at least 5% damage */ diff --git a/core/src/mindustry/content/StatusEffects.java b/core/src/mindustry/content/StatusEffects.java index 6752cf68e6..4cdfadec76 100644 --- a/core/src/mindustry/content/StatusEffects.java +++ b/core/src/mindustry/content/StatusEffects.java @@ -33,7 +33,7 @@ public class StatusEffects implements ContentList{ freezing = new StatusEffect("freezing"){{ speedMultiplier = 0.6f; - armorMultiplier = 0.8f; + healthMultiplier = 0.8f; effect = Fx.freezing; init(() -> { @@ -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");