diff --git a/core/assets-raw/sprites/units/merui-cell.png b/core/assets-raw/sprites/units/merui-cell.png new file mode 100644 index 0000000000..9548b30a9a Binary files /dev/null and b/core/assets-raw/sprites/units/merui-cell.png differ diff --git a/core/assets-raw/sprites/units/merui-leg-base.png b/core/assets-raw/sprites/units/merui-leg-base.png index 8592979a68..efcda87291 100644 Binary files a/core/assets-raw/sprites/units/merui-leg-base.png and b/core/assets-raw/sprites/units/merui-leg-base.png differ diff --git a/core/assets-raw/sprites/units/merui-leg.png b/core/assets-raw/sprites/units/merui-leg.png index 020566c493..aad88b1de6 100644 Binary files a/core/assets-raw/sprites/units/merui-leg.png and b/core/assets-raw/sprites/units/merui-leg.png differ diff --git a/core/assets-raw/sprites/units/merui-weapon-heat.png b/core/assets-raw/sprites/units/merui-weapon-heat.png new file mode 100644 index 0000000000..764158d51b Binary files /dev/null and b/core/assets-raw/sprites/units/merui-weapon-heat.png differ diff --git a/core/assets-raw/sprites/units/merui-weapon.png b/core/assets-raw/sprites/units/merui-weapon.png new file mode 100644 index 0000000000..84eee1be40 Binary files /dev/null and b/core/assets-raw/sprites/units/merui-weapon.png differ diff --git a/core/src/mindustry/content/Fx.java b/core/src/mindustry/content/Fx.java index 86199b5f81..ca6ebce0bd 100644 --- a/core/src/mindustry/content/Fx.java +++ b/core/src/mindustry/content/Fx.java @@ -589,6 +589,24 @@ public class Fx{ Drawf.light(e.x, e.y, 20f, e.color, 0.6f * e.fout()); }), + hitSquaresColor = new Effect(14, e -> { + color(Color.white, e.color, e.fin()); + + e.scaled(7f, s -> { + stroke(0.5f + s.fout()); + Lines.circle(e.x, e.y, s.fin() * 5f); + }); + + stroke(0.5f + e.fout()); + + randLenVectors(e.id, 5, e.fin() * 17f, (x, y) -> { + float ang = Mathf.angle(x, y); + Fill.square(e.x + x, e.y + y, e.fout() * 3.2f, ang); + }); + + Drawf.light(e.x, e.y, 20f, e.color, 0.6f * e.fout()); + }), + hitFuse = new Effect(14, e -> { color(Color.white, Pal.surge, e.fin()); @@ -1412,6 +1430,13 @@ public class Fx{ Drawf.tri(e.x, e.y, w, 3f * e.fout(), e.rotation + 180f); }), + shootSmallColor = new Effect(8, e -> { + color(e.color, Color.gray, e.fin()); + float w = 1f + 5 * e.fout(); + Drawf.tri(e.x, e.y, w, 15f * e.fout(), e.rotation); + Drawf.tri(e.x, e.y, w, 3f * e.fout(), e.rotation + 180f); + }), + shootHeal = new Effect(8, e -> { color(Pal.heal); float w = 1f + 5 * e.fout(); diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index 31f50ffb43..e9dd6d8c18 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -2831,12 +2831,13 @@ public class UnitTypes{ //region erekir - mech merui = new ErekirUnitType("merui"){{ - speed = 0.75f; - drag = 0.1f; + speed = 0.7f; + drag = 0.11f; hitSize = 9f; - rotateSpeed = 3.5f; - health = 700; - armor = 5f; + rotateSpeed = 3f; + health = 680; + armor = 4f; + legStraightness = 0.3f; legCount = 6; legLength = 8f; @@ -2856,6 +2857,55 @@ public class UnitTypes{ visualElevation = 0.1f; groundLayer = Layer.legUnit - 1f; + targetAir = false; + + weapons.add(new Weapon("merui-weapon"){{ + mirror = false; + x = 0f; + y = 1f; + shootY = 4f; + reload = 60f; + cooldownTime = 42f; + heatColor = Pal.turretHeat; + + bullet = new ArtilleryBulletType(3f, 40){{ + shootEffect = new MultiEffect(Fx.shootSmallColor, new Effect(9, e -> { + color(Color.white, e.color, e.fin()); + stroke(0.7f + e.fout()); + Lines.square(e.x, e.y, e.fin() * 5f, e.rotation + 45f); + + Drawf.light(e.x, e.y, 23f, e.color, e.fout() * 0.7f); + })); + + collidesTiles = true; + recoil = 0.5f; + backColor = hitColor = Pal.techBlue; + frontColor = Color.white; + + knockback = 0.8f; + lifetime = 50f; + width = height = 9f; + splashDamageRadius = 19f; + splashDamage = 30f; + + trailLength = 27; + trailWidth = 2.5f; + trailEffect = Fx.none; + trailColor = backColor; + + trailInterp = Interp.slope; + + shrinkX = 0.6f; + shrinkY = 0.2f; + + hitEffect = despawnEffect = new MultiEffect(Fx.hitSquaresColor, new WaveEffect(){{ + colorFrom = colorTo = Pal.techBlue; + sizeTo = splashDamageRadius + 2f; + lifetime = 9f; + strokeFrom = 2f; + }}); + }}; + }}); }}; diff --git a/core/src/mindustry/game/FogControl.java b/core/src/mindustry/game/FogControl.java index 0e446ea5af..2f13cf4d80 100644 --- a/core/src/mindustry/game/FogControl.java +++ b/core/src/mindustry/game/FogControl.java @@ -61,7 +61,7 @@ public final class FogControl implements CustomChunk{ }); Events.on(TileChangeEvent.class, event -> { - if(state.rules.fog && event.tile.build != null && event.tile.isCenter() && !event.tile.build.team.isAI() && event.tile.block().flags.contains(BlockFlag.hasFogRadius)){ + if(state.rules.fog && event.tile.build != null && event.tile.isCenter() && !event.tile.build.team.isOnlyAI() && event.tile.block().flags.contains(BlockFlag.hasFogRadius)){ var data = data(event.tile.team()); if(data != null){ data.dynamicUpdated = true; @@ -78,7 +78,7 @@ public final class FogControl implements CustomChunk{ //on tile removed, dynamic fog goes away Events.on(TilePreChangeEvent.class, e -> { - if(state.rules.fog && e.tile.build != null && !e.tile.build.team.isAI() && e.tile.block().flags.contains(BlockFlag.hasFogRadius)){ + if(state.rules.fog && e.tile.build != null && !e.tile.build.team.isOnlyAI() && e.tile.block().flags.contains(BlockFlag.hasFogRadius)){ var data = data(e.tile.team()); if(data != null){ data.dynamicUpdated = true; @@ -210,7 +210,7 @@ public final class FogControl implements CustomChunk{ for(var team : state.teams.present){ //AI teams do not have fog - if(!team.team.isAI()){ + if(!team.team.isOnlyAI()){ //separate for each team unitEventQueue.clear(); diff --git a/core/src/mindustry/game/Team.java b/core/src/mindustry/game/Team.java index 6b4b305fa4..6844bc7661 100644 --- a/core/src/mindustry/game/Team.java +++ b/core/src/mindustry/game/Team.java @@ -103,11 +103,16 @@ public class Team implements Comparable{ return state.teams.isActive(this); } - /** @return whether this team is solely comprised of AI, with no players. */ + /** @return whether this team is supposed to be AI-controlled. */ public boolean isAI(){ return (state.rules.waves || state.rules.attackMode) && this == state.rules.waveTeam; } + /** @return whether this team is solely comprised of AI (with no players possible). */ + public boolean isOnlyAI(){ + return isAI() && data().players.size == 0; + } + /** @return whether this team needs a flow field for "dumb" wave pathfinding. */ public boolean needsFlowField(){ return isAI() && !rules().rtsAi;